Compare commits

...

93 Commits

Author SHA1 Message Date
Elena Lepilkina
88e4f79050 One more experiment with inline threshold 2021-05-14 09:19:09 +03:00
Elena Lepilkina
47a8a7d7ec Increase inline threshold to improve performance 2021-05-13 16:09:07 +03:00
Elena Lepilkina
9d857fbb30 Fixes after rebase 2021-05-13 14:40:27 +03:00
Elena Lepilkina
89f4a8a72b Removed extra update of debug info 2021-05-13 11:43:18 +03:00
Elena Lepilkina
525d7c37a4 [K/N] Replace invokes with calls in LLVM bitcode for functions without extra slots 2021-05-13 11:40:03 +03:00
Pavel Punegov
53bf0b1c42 Update Build gradle plugin to 0.0.28 2021-05-12 10:34:36 +03:00
Pavel Punegov
540c69ab89 [native] VersionGenerator: fix error string 2021-05-12 10:34:36 +03:00
Pavel Punegov
86041096fd Return milestone property back to support older versions of plugins
Older gradle plugin's NativeCompilerDownloader uses milestone property.
2021-05-12 10:34:36 +03:00
Pavel Punegov
f82c28bd79 Revert "[kotlin-gradle-plugin] workaround for old k/n artifacts"
This reverts commit 5c80dbfd
2021-05-12 10:34:36 +03:00
Pavel Punegov
a0d35e56a9 Revert "[tests][kotlin-gradle-plugin] workaround for old k/n artifacts"
This reverts commit f051119c to drop obsolete native version support
2021-05-12 10:34:35 +03:00
Pavel Punegov
fa525a8359 [native] Support milestones in meta versions
Add milestones to MetaVersion to replace standalone parameter in
compiler version generator. This makes native version match Kotlin one.
2021-05-12 10:34:35 +03:00
Ilmir Usmanov
c4ddf3530d Use GETFIELD instead of unbox-impl inside inline classes
#KT-36783 Fixed
2021-05-12 06:50:06 +00:00
Jinseong Jeon
e5f3091f2c FIR/UAST: commonize KotlinUFile
We can avoid explicit creation of UAnnotation and UImportStatement if we
use languagePlugin as a UAST element factory.
2021-05-11 21:43:02 +02:00
Jinseong Jeon
5dc0b52e38 FIR UAST: fix/test allCommentsInFile in UFile 2021-05-11 21:43:02 +02:00
Jinseong Jeon
03b5c14944 FIR UAST: enable remaining legacy test data
This should have been part of commit 7f627ab4
2021-05-11 21:43:02 +02:00
Tianyu Geng
302e0fa46b FIR IDE: add quickfix AddWhenElseBranchFix 2021-05-11 21:42:45 +02:00
Jinseong Jeon
8e10b5fdec FIR: introduce FirExpressionWithSmartcastToNull
This new kind of expression encompasses the nullability of the original
expression after null check (or equivalent `is Nothing?` check).

Unlike FirExpressionWithSmartcast, this expression won't be materialized
during conversion to backend IR. Also, Nothing? is discarded when
computing the intersection of possible types from smartcast info.
In that way, Nothing? is not used during resolution, while such
smartcast info is stored in it (and the expression kind itself).
2021-05-11 21:28:44 +03:00
Jinseong Jeon
8da183e4f4 FIR DFA: filter out unwanted implcations from processEqNull
^KT-41015 fixed
2021-05-11 21:28:43 +03:00
Xin Wang
b9209962cd CLI: Add documentation for -J argument in kotlinc -help 2021-05-11 19:50:24 +02:00
Dmitriy Novozhilov
1407af6301 [Test] Sort failed exceptions in JUnit5Assertions.assertAll
This is needed to throw FileComparisonFailure first, because idea
  test UI can not show multiple diff windows for multiple assertions
  and shows only first, which is not useful
2021-05-11 20:07:35 +03:00
Dmitriy Novozhilov
2530ae6b3d [Test] Split IR verification and IR dump to different handlers 2021-05-11 20:07:34 +03:00
Dmitriy Novozhilov
c9cd49d34f [Test] Temporary remove test for KT-22379
This is needed because this test breaks IDE when whit file is indexed.
This test will be returned after release of new kotlin plugins for IDEA
2021-05-11 19:45:43 +03:00
Andrey Zinovyev
89f0a790c9 [lombok] Map lombok MODULE to java PackageVisibility
Because that's what lombok does
#KT-46469 Fixed
2021-05-11 19:18:39 +03:00
Andrey Zinovyev
468fc86a3f [lombok] Fix fallback to config for array annotation's parameter
If annotation's parameter is not explicitly defined, it should be
taken from config
#KT-46529 Fixed
2021-05-11 19:18:37 +03:00
Andrey Zinovyev
57d3f98ece [lombok] Config keys are case-insensitive
#KT-46531 Fixed
2021-05-11 19:18:36 +03:00
Alexander Udalov
c898805ac5 CLI: improve path relativization for compiler messages
On Windows, the absolute file for the root of the drive is `"C:\"`,
which differs from the absolute file for any other directory, which
doesn't end with `\`. This resulted in incorrect trimming of the first
character of the path name in `descendantRelativeTo`.

Also, do not use canonicalPath because there is no point in expanding
symbolic links here.

 #KT-40979 Fixed
2021-05-11 18:44:14 +03:00
Alexander Udalov
f63dac26e6 Minor, extract ProgramWithDependencyOnCompiler for tests
Also use ProcessBuilder instead of GeneralCommandLine for simplicity.
2021-05-11 18:44:12 +03:00
Mads Ager
d397efb2bd [JVM IR] Copy attributes for JVM_STATIC_WRAPPERS. 2021-05-11 16:26:04 +02:00
Mads Ager
3db5ba98ad [JVM IR] Do not insert Nothing handling in JvmStatic wrapper.
Fixes KT-46568.
2021-05-11 16:26:04 +02:00
Dmitriy Novozhilov
3532ce7fbc [Parser] Fix OOM in parsing of incorrect string literals
^KT-46455 Fixed
KT-34410
KT-46564
2021-05-11 16:43:29 +03:00
Mikhail Glukhikh
c284eab2dd FIR / FE 1.0: fix exception for lambda with unresolved name
#KT-46515 Fixed
2021-05-11 15:41:06 +03:00
Stanislav Erokhin
eb4bb9554d Add ReplaceInvoke adn ReplaceCallWithUnaryOperator intention support
Surprisingly all test passed
2021-05-11 12:48:18 +02:00
Stanislav Erokhin
85d9e96632 Partially support call with errors
Cases with no candidates or with Ambiguity is not supported yet
2021-05-11 12:48:17 +02:00
Stanislav Erokhin
080a832605 Fix argument mapping for lambda arguments and default arguments
Maybe for other elements ValueArgument itself used as SourceElement
2021-05-11 12:48:17 +02:00
Stanislav Erokhin
335c5a03b6 Add correct equals/hashCode to KtSymbolBasedAbstractTypeConstructor
Previously there were no equals/hashCode implementation.
Because of that subtyping not working properly. That is because in
subtyping we have checks that type constructors are equals

Also toString was added so now it is a bit easier to debug code
involving the KtSymbolBasedAbstractTypeConstructor
2021-05-11 12:48:16 +02:00
Stanislav Erokhin
dc1ce19db9 Extract some logic from AbstractTypeConstructor to reuse it later
In FE10-binding I would like to re-use equal and hashCode mechanics
that was implemented in AbstractTypeConstructor, but I don't need
the supertype implementation, because it already there in FIR
2021-05-11 12:48:16 +02:00
Nikita Bobko
bee8c0bb90 Publish :compiler:test-infrastructure for ide 2021-05-11 12:36:59 +02:00
Vasily Levchenko
c2a46baa77 [build][kotlin-native][test] fix dist dependencies for test targets 2021-05-11 05:47:17 +00:00
Ilmir Usmanov
640d263ae1 Do not unbox nullable Result, since before usage it is coerced
#KT-46505
2021-05-11 05:49:24 +02:00
pyos
656c2496a6 JVM_IR: omit bound receiver in IrExpressionLambdaImpl parameters
and remove a hack intended to replace the missing type conversions this
caused.

 #KT-46505 Fixed
2021-05-11 05:49:20 +02:00
pyos
614d529168 JVM: remove LambdaInfo.invokeMethodDescriptor 2021-05-11 05:49:17 +02:00
Ilya Kirillov
47dc524763 FIR IDE: remove KtUnsubstitutedScope/KtSubstitutedScope as it designed wrong 2021-05-11 01:36:13 +03:00
Ilya Kirillov
90798d8857 FIR IDE: add KDoc for KtScope, choose better names for KtScope members 2021-05-11 01:36:11 +03:00
Ilya Kirillov
f9087a8ab1 FIR IDE: update testdata after changes in symbols 2021-05-11 01:36:10 +03:00
Ilya Kirillov
accc0e3761 FIR IDE: make KtCallableSymbol to be always KtPossiblyExtensionSymbol 2021-05-11 01:36:09 +03:00
Ilya Kirillov
0ba6412f96 FIR IDE: remove KtTypedSymbol interface as all its inheritors are KtCallableSymbol 2021-05-11 01:36:07 +03:00
Jinseong Jeon
bbe5cf0a70 FIR/UAST: clarify what module we should not depend on 2021-05-10 20:23:19 +02:00
Ilya Kirillov
e14848740a FIR IDE: forbid executing write action inside analyse call 2021-05-10 20:44:23 +03:00
Ilya Muradyan
626c1d3b48 [Scripting] Fix repository ID generation for Maven resolver 2021-05-10 19:40:32 +03:00
Ilya Muradyan
7cea639209 chore: fix typo in comment 2021-05-10 19:40:31 +03:00
Dmitry Petrov
ac0aaff611 JVM_IR KT-46562 don't use LambdaMetafactory for Serializable SAMs
TODO support serializable lambdas creation with LambdaMetafactory
2021-05-10 14:54:14 +03:00
Jinseong Jeon
bdfc879f00 FIR checker: report UNINITIALIZED_PARAMETER 2021-05-10 14:26:14 +03:00
Stanislav Erokhin
d2f831b635 Handle exception during intention background computation in tests
Our test infrastructure (in particular, muting mechanics) rely on
thrown exception during doTestFor function call. But if the
exception happened on background thread, then here we'll get only
TimeOutException but the actual exception won't be reported during
doTestFor call. It would be reported later by the common IDEA test
framework and bypass our mute mechanics
2021-05-10 14:04:04 +03:00
Stanislav Erokhin
7ac599520e Add first prototype of BindingContext implementation by FIR
Add ImportMemberIntention intention as a test.
In this commit all failed test were disabled, necessary fixes will be
added in the following commits
2021-05-10 14:04:03 +03:00
Stanislav Erokhin
6919f3dbb5 Move KotlinCacheServiceImpl to plugin-common.xml
This was done to prevent fir plugin from loading FE 1.0 services
2021-05-10 14:04:02 +03:00
Jinseong Jeon
bf85b110da FIR DFA: remove updatedAliasDiff from PersistentFlow
It is no longer used after element-wise join (a5389b06)
2021-05-10 12:16:04 +03:00
Mikhael Bogdanov
cd7841ceed Generate type annotations on class type parameters bounds
#KT-13228
 #KT-46539 Fixed
2021-05-10 12:12:21 +03:00
Mikhael Bogdanov
f574f89f78 Generate class annotation in AbstractAsmLikeInstructionListingTest 2021-05-10 12:12:20 +03:00
Mikhael Bogdanov
40eeee48b6 Extract generation of type parameters annotations and annotation on their bounds into utils 2021-05-10 12:12:19 +03:00
Mikhael Bogdanov
cbe3c66156 Generate function type parameter annotations and type annotations on their bounds into bytecode
Generate type parameter annotation by default for `-Xjvm-target 1.8` and above

 #KT-46539
 #KT-13228
 #KT-46545 Fixed
2021-05-10 12:12:18 +03:00
Mikhael Bogdanov
209ec68591 Make copy for disabled ir tests 2021-05-10 12:12:16 +03:00
Mikhael Bogdanov
5ff4d648f4 Render generic signature in type parameters tests 2021-05-10 12:12:15 +03:00
Mikhael Bogdanov
6182228de8 Render all annotations in type parameters tests 2021-05-10 12:12:14 +03:00
Vladimir Dolzhenko
c98dba6aea Do not set diagnostics callback if it is already set
Relates to #KT-37702
2021-05-10 09:59:16 +02:00
Vladimir Dolzhenko
cf5e6b242b Wrap exception with file details
Relates to #KT-39776
2021-05-07 23:48:12 +02:00
Ilya Muradyan
e9af2849ef Add Kotlin DeprecationLevel into the REPL completion 2021-05-07 19:56:21 +03:00
Mads Ager
6bc4e124fb [JVM_IR] Guard against infinite recursion in JvmIrCodegenFactory.
Fixed KTIJ-11580.
2021-05-07 17:58:49 +02:00
n-p-s
d70b889004 Update declarations to be searchable by their JvmName annotation
Relates to #KT-23653
2021-05-07 17:43:26 +03:00
pyos
36a25353e9 JVM_IR: permit @NoArg if super constructor is already zero-argument
#KT-46537 Fixed
2021-05-07 16:22:30 +02:00
Mikhail Glukhikh
ac9e8f667d Simplify code in Fir2IrConversionScope.returnTarget 2021-05-07 17:06:34 +03:00
Mikhail Glukhikh
05872fc6a8 Support captured types in ConeTypeCompatibilityChecker 2021-05-07 17:06:34 +03:00
Mikhail Glukhikh
df815a64cf FirEqualityCompatibilityChecker: rename file 2021-05-07 17:06:34 +03:00
Mikhail Glukhikh
6a51ddf755 FirEqualityCompatibilityChecker: add exception wrapper 2021-05-07 17:06:34 +03:00
Andrei Klunnyi
b7eded6e48 KT-46146 no 'protected' for final classes
Intention to change final class constructor visibility to 'protected'
was erroneous. This commit removes it.
2021-05-07 12:47:40 +00:00
Andrei Klunnyi
e56a3b3c30 KT-46146 'protected' and 'private' only for sealed constructors
Prior to this commit we suggested two invalid intentions for sealed
class constructors: change visibility to 'public' and 'internal'.

^KT-46146 Fixed
2021-05-07 12:47:39 +00:00
Andrei Klunnyi
686368749a KT-46146 'protected' is unavailable for primary constructors
Prior to this commit intention to change primary constructor visibility
to 'protected' was filtered out.
2021-05-07 12:47:38 +00:00
Alina Dolgikh
7388e60869 Add link to Kotlin 1.5 Event registration
As an experiment, we would like to try promotion in the Github repository.
2021-05-07 14:40:14 +02:00
Ilya Muradyan
042ac5555c Merge pull request #4342 from JetBrains/rr/ileasile/completion-for-function-params
[REPL] Add completion for the call named parameters
2021-05-07 15:11:12 +03:00
Mikhail Glukhikh
27903b4cd6 Configuration fix: make fir2ir tests depend on 'dist' 2021-05-07 10:32:47 +03:00
Alexander Udalov
d306d8a90e JVM IR: cast indy-SAM receiver type from KFunctionN to FunctionN
#KT-46512 Fixed
2021-05-07 00:53:31 +03:00
Ilya Kirillov
124bd559de FIR IDE: fix failing AbstractOverrideImplementTest tests on Windows
Before the System.lineSeparator() was used for splitting KtFile.text into lines.
In IJ all lines has UNIX file endings, so it failed on Windows TC agent
2021-05-07 00:40:52 +03:00
Mikhail Glukhikh
f83841a34f Cleanup FirHelpers (inline / remove / reduce visibility) 2021-05-07 00:40:51 +03:00
Tianyu Geng
9273c6326e FIR IDE: workaround deadlock when resolving class members
When listing members in a class, we need to resolve super types. But if
a super type is defined in another file, this file may not have been
resolved. In this case, listing the members would require resolving the
unresolved file, which can only be done in a write lock.

Before this change, KtFirScopeProvider only acquire the read lock, which
then causes read/write deadlock when the logic tries to further resolve
super types defined in other files. This change makes KtFirScopeProvider
acquire a write lock in the beginning so resolving can happen correctly
later.
2021-05-07 00:40:50 +03:00
Tianyu Geng
7a745cfe5c FIR IDE: Remove unnecessary renderAnnotations option 2021-05-07 00:40:48 +03:00
Tianyu Geng
417c841f77 FIR IDE: Move write actions out of analyze block 2021-05-07 00:40:47 +03:00
Tianyu Geng
e56b39bbd8 FIR IDE: fix typo in package name 2021-05-07 00:40:46 +03:00
Tianyu Geng
d09be811f0 FIR: make class delegation field a fake source
Previously, the FirFieldImpl generated from class delegation has a real
source. This causes troubles in the IDE. This change adds a new fake
source kind for class delegation fields.
2021-05-07 00:40:44 +03:00
Tianyu Geng
0b8b20eda0 FIR IDE: fix KtFirScopeProvider
Currently FIR IDE throws exceptions when enumerating members in this
scope if the class has delegate super types.

java.lang.IllegalStateException: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl Tjava.lang.IllegalStateException: java.lang.IllegalStateException: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl T
	at org.jetbrains.kotlin.test.KotlinTestUtils.lambda$runTestWithThrowable$3(KotlinTestUtils.java:498)
	at org.jetbrains.kotlin.test.MuteWithDatabaseKt.runTest(muteWithDatabase.kt:96)
	at org.jetbrains.kotlin.test.KotlinTestUtils.runTestWithThrowable(KotlinTestUtils.java:493)
	at org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCaseBase.runTest(KotlinLightCodeInsightFixtureTestCaseBase.java:93)
	at com.intellij.testFramework.UsefulTestCase.defaultRunBare(UsefulTestCase.java:394)
	at com.intellij.testFramework.EdtTestUtil$Companion$runInEdtAndWait$1.invoke(EdtTestUtil.kt:18)
	at com.intellij.testFramework.EdtTestUtil$Companion$runInEdtAndWait$1.invoke(EdtTestUtil.kt:13)
	at com.intellij.testFramework.EdtTestUtilKt$runInEdtAndWait$1.run(EdtTestUtil.kt:50)
	at com.intellij.openapi.application.TransactionGuardImpl$2.run(TransactionGuardImpl.java:201)
	at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:802)
	at com.intellij.openapi.application.impl.ApplicationImpl.lambda$invokeAndWait$8(ApplicationImpl.java:475)
	at com.intellij.openapi.application.impl.LaterInvocator$1.run(LaterInvocator.java:126)
	at com.intellij.openapi.application.impl.FlushQueue.doRun(FlushQueue.java:84)
	at com.intellij.openapi.application.impl.FlushQueue.runNextEvent(FlushQueue.java:132)
	at com.intellij.openapi.application.impl.FlushQueue.flushNow(FlushQueue.java:47)
	at com.intellij.openapi.application.impl.FlushQueue$FlushNow.run(FlushQueue.java:188)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
	at java.awt.EventQueue.access$500(EventQueue.java:97)
	at java.awt.EventQueue$3.run(EventQueue.java:709)
	at java.awt.EventQueue$3.run(EventQueue.java:703)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
	at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:971)
	at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:841)
	at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$8(IdeEventQueue.java:452)
	at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:744)
	at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$9(IdeEventQueue.java:451)
	at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:802)
	at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:499)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Caused by: java.lang.IllegalStateException: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl T
	at org.jetbrains.kotlin.fir.types.FirTypeUtilsKt.getConeType(FirTypeUtils.kt:33)
	at org.jetbrains.kotlin.fir.scopes.KotlinScopeProviderKt.scopeForSupertype(KotlinScopeProvider.kt:111)
	at org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider.getUseSiteMemberScope(KotlinScopeProvider.kt:42)
	at org.jetbrains.kotlin.fir.scopes.KotlinScopeProviderKt.unsubstitutedScope(KotlinScopeProvider.kt:83)
	at org.jetbrains.kotlin.idea.frontend.api.fir.components.KtFirScopeProvider$getMemberScope$lambda-3$lambda-2$$inlined$withFirForScope$1.invoke(FirRefWithValidityCheck.kt:83)
	at org.jetbrains.kotlin.idea.frontend.api.fir.components.KtFirScopeProvider$getMemberScope$lambda-3$lambda-2$$inlined$withFirForScope$1.invoke(FirRefWithValidityCheck.kt:41)
	at org.jetbrains.kotlin.idea.fir.low.level.api.api.LowLevelFirApiFacadeKt.withFirDeclaration(LowLevelFirApiFacade.kt:209)
	at org.jetbrains.kotlin.idea.frontend.api.fir.components.KtFirScopeProvider.getMemberScope(KtFirScopeProvider.kt:323)
	at org.jetbrains.kotlin.idea.frontend.api.components.KtScopeProviderMixIn$DefaultImpls.getMemberScope(KtScopeProvider.kt:34)
	at org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession.getMemberScope(KtAnalysisSession.kt:26)
	at org.jetbrains.kotlin.idea.core.overrideImplement.KtOverrideMembersHandler.getOverridableMembers(KtOverrideMembersHandler.kt:54)
	at org.jetbrains.kotlin.idea.core.overrideImplement.KtOverrideMembersHandler.collectMembers(KtOverrideMembersHandler.kt:35)
	at org.jetbrains.kotlin.idea.core.overrideImplement.KtOverrideMembersHandler.collectMembersToGenerate(KtOverrideMembersHandler.kt:28)
	at org.jetbrains.kotlin.idea.codeInsight.AbstractOverrideImplementTest.doMultiOverrideImplement(AbstractOverrideImplementTest.kt:141)
	at org.jetbrains.kotlin.idea.codeInsight.AbstractOverrideImplementTest.doMultiFileTest(AbstractOverrideImplementTest.kt:98)
	at org.jetbrains.kotlin.idea.codeInsight.AbstractOverrideImplementTest.doMultiOverrideFileTest(AbstractOverrideImplementTest.kt:54)
	at org.jetbrains.kotlin.idea.codeInsight.OverrideImplementTest.testDelegatedMembers(OverrideImplementTest.kt:121)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at junit.framework.TestCase.runTest(TestCase.java:176)
	at com.intellij.testFramework.UsefulTestCase.lambda$runTest$9(UsefulTestCase.java:331)
	at com.intellij.openapi.application.impl.ApplicationImpl.invokeAndWait(ApplicationImpl.java:462)
	at com.intellij.openapi.application.impl.ApplicationImpl.invokeAndWait(ApplicationImpl.java:480)
	at com.intellij.testFramework.UsefulTestCase.invokeTestRunnable(UsefulTestCase.java:378)
	at com.intellij.testFramework.UsefulTestCase.runTest(UsefulTestCase.java:350)
	at org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCaseBase.lambda$runTest$0(KotlinLightCodeInsightFixtureTestCaseBase.java:93)
	at org.jetbrains.kotlin.test.KotlinTestUtils.lambda$runTestWithThrowable$3(KotlinTestUtils.java:495)
	... 36 more
.. 112 more
2021-05-07 00:40:42 +03:00
Tianyu Geng
53aafbd7d9 FIR IDE: enable override implement test for FIR 2021-05-07 00:40:41 +03:00
Tianyu Geng
00031c8eb1 FIR IDE: add action to override/implement missing members
This commit adds the following actions:

- quickfix to implement missing members
- quickfix to implement missing members as constructor parameters
- action to implement members (Code - Generate - Implement)
- action to override members (Code - Generate - Override)

The current implementation is still missing some pieces, which will be
addressed in future changes.

- fully qualified names are not shorten
- some Kotlin types are not rendered correctly
2021-05-07 00:40:40 +03:00
Tianyu Geng
34387e228f FIR IDE: extract common logic idea.core.overrideImplement
Also rename OverrideImplementMemberHandler to GenerateMemberHandler to
align with the naming of its member functions.
2021-05-07 00:40:38 +03:00
Tianyu Geng
06ba143afe FIR IDE: quickfix to make class abstract if member not implemented 2021-05-07 00:40:37 +03:00
Ilya Muradyan
b771f9eea4 [REPL] Add completion for the call named parameters 2021-05-04 04:40:00 +03:00
637 changed files with 9494 additions and 1581 deletions

View File

@@ -4,6 +4,8 @@
[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0)
[![Revved up by Gradle Enterprise](https://img.shields.io/badge/Revved%20up%20by-Gradle%20Enterprise-06A0CE?logo=Gradle&labelColor=02303A)](https://ge.jetbrains.com/scans?search.rootProjectNames=Kotlin)
[Join Kotlin 1.5 Online Event on May 25, 2021!](https://pages.jetbrains.com/kotlin-online-event-2021/github-readme)
# Kotlin Programming Language
Welcome to [Kotlin](https://kotlinlang.org/)!

View File

@@ -30,7 +30,7 @@ buildscript {
dependencies {
bootstrapCompilerClasspath(kotlin("compiler-embeddable", bootstrapKotlinVersion))
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.27")
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.28")
classpath(kotlin("gradle-plugin", bootstrapKotlinVersion))
classpath(kotlin("serialization", bootstrapKotlinVersion))
classpath("org.jetbrains.dokka:dokka-gradle-plugin:0.9.17")
@@ -335,6 +335,7 @@ extra["tasksWithWarnings"] = listOf(
":kotlin-stdlib:compileTestKotlin",
":kotlin-stdlib-jdk7:compileTestKotlin",
":kotlin-stdlib-jdk8:compileTestKotlin",
":plugins:uast-kotlin-base:compileKotlin",
":plugins:uast-kotlin:compileKotlin",
":plugins:uast-kotlin:compileTestKotlin",
":plugins:uast-kotlin-fir:compileKotlin",
@@ -850,7 +851,8 @@ tasks {
":idea:idea-frontend-api:test",
":idea:idea-frontend-fir:test",
":idea:idea-frontend-fir:idea-fir-low-level-api:test",
":plugins:uast-kotlin-fir:test"
":plugins:uast-kotlin-fir:test",
":idea:idea-fir-fe10-binding:test"
)
}
@@ -967,6 +969,7 @@ tasks {
":prepare:ide-plugin-dependencies:compiler-components-for-jps:publish",
":prepare:ide-plugin-dependencies:parcelize-compiler-plugin-for-ide:publish",
":prepare:ide-plugin-dependencies:lombok-compiler-plugin-for-ide:publish",
":prepare:ide-plugin-dependencies:kotlin-compiler-tests-for-ide:publish",
":kotlin-script-runtime:publish",
":kotlin-script-util:publish",
":kotlin-scripting-common:publish",

View File

@@ -22,7 +22,7 @@ buildscript {
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.27")
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.28")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${project.bootstrapKotlinVersion}")
classpath("org.jetbrains.kotlin:kotlin-sam-with-receiver:${project.bootstrapKotlinVersion}")
}
@@ -144,7 +144,7 @@ java {
dependencies {
implementation(kotlin("stdlib", embeddedKotlinVersion))
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${project.bootstrapKotlinVersion}")
implementation("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.27")
implementation("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.28")
implementation("com.gradle.publish:plugin-publish-plugin:0.14.0")
implementation("net.rubygrapefruit:native-platform:${property("versions.native-platform")}")

View File

@@ -21,7 +21,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.27")
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.28")
}
}

View File

@@ -274,13 +274,15 @@ fun Project.publishProjectJars(projects: List<String>, libraryDependencies: List
javadocJar()
}
fun Project.publishTestJar(projectName: String) {
fun Project.publishTestJar(projects: List<String>) {
apply<JavaPlugin>()
val fatJarContents by configurations.creating
dependencies {
fatJarContents(project(projectName, configuration = "tests-jar")) { isTransitive = false }
for (projectName in projects) {
fatJarContents(project(projectName, configuration = "tests-jar")) { isTransitive = false }
}
}
publish()
@@ -297,7 +299,7 @@ fun Project.publishTestJar(projectName: String) {
sourcesJar {
from {
project(projectName).testSourceSet.allSource
projects.map { project(it).testSourceSet.allSource }
}
}

View File

@@ -47,7 +47,9 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgu
abstract val invokeMethod: Method
abstract val invokeMethodDescriptor: FunctionDescriptor
abstract val invokeMethodParameters: List<KotlinType?>
abstract val invokeMethodReturnType: KotlinType?
abstract val capturedVars: List<CapturedParamDesc>
@@ -98,14 +100,16 @@ class PsiDefaultLambda(
offset: Int,
needReification: Boolean
) : DefaultLambda(lambdaClassType, capturedArgs, parameterDescriptor, offset, needReification) {
override fun mapAsmSignature(sourceCompiler: SourceCompilerForInline): Method {
return sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod
}
override fun mapAsmSignature(sourceCompiler: SourceCompilerForInline, descriptor: FunctionDescriptor): Method =
sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(descriptor).asmMethod
override fun findInvokeMethodDescriptor(): FunctionDescriptor =
override fun findInvokeMethodDescriptor(isPropertyReference: Boolean): FunctionDescriptor =
parameterDescriptor.type.memberScope
.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND)
.single()
.single().let {
// property reference generates erased 'get' method
if (isPropertyReference) it.original else it
}
}
abstract class DefaultLambda(
@@ -124,7 +128,13 @@ abstract class DefaultLambda(
final override lateinit var invokeMethod: Method
private set
override lateinit var invokeMethodDescriptor: FunctionDescriptor
private lateinit var invokeMethodDescriptor: FunctionDescriptor
override val invokeMethodParameters: List<KotlinType?>
get() = invokeMethodDescriptor.valueParameters.map { it.returnType } // should be FunctionN, so no extension receiver
override val invokeMethodReturnType: KotlinType?
get() = invokeMethodDescriptor.returnType
final override lateinit var capturedVars: List<CapturedParamDesc>
private set
@@ -155,10 +165,7 @@ abstract class DefaultLambda(
}
}, ClassReader.SKIP_CODE or ClassReader.SKIP_FRAMES or ClassReader.SKIP_DEBUG)
invokeMethodDescriptor = findInvokeMethodDescriptor().let {
//property reference generates erased 'get' method
if (isPropertyReference) it.original else it
}
invokeMethodDescriptor = findInvokeMethodDescriptor(isPropertyReference)
val descriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *capturedArgs)
val constructor = getMethodNode(classBytes, "<init>", descriptor, lambdaClassType)?.node
@@ -182,7 +189,7 @@ abstract class DefaultLambda(
val methodName = (if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString()
val signature = mapAsmSignature(sourceCompiler)
val signature = mapAsmSignature(sourceCompiler, invokeMethodDescriptor)
node = getMethodNode(classBytes, methodName, signature.descriptor, lambdaClassType, signatureAmbiguity = true)
?: error("Can't find method '$methodName$signature' in '${classReader.className}'")
@@ -195,9 +202,10 @@ abstract class DefaultLambda(
}
}
protected abstract fun mapAsmSignature(sourceCompiler: SourceCompilerForInline): Method
protected abstract fun mapAsmSignature(sourceCompiler: SourceCompilerForInline, descriptor: FunctionDescriptor): Method
protected abstract fun findInvokeMethodDescriptor(): FunctionDescriptor
// TODO: get rid of this; descriptors should *only* be used by PsiDefaultLambda
protected abstract fun findInvokeMethodDescriptor(isPropertyReference: Boolean): FunctionDescriptor
private companion object {
val PROPERTY_REFERENCE_SUPER_CLASSES =
@@ -221,7 +229,6 @@ abstract class ExpressionLambda(isCrossInline: Boolean) : LambdaInfo(isCrossInli
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
}
abstract fun getInlineSuspendLambdaViewDescriptor(): FunctionDescriptor
abstract fun isCapturedSuspend(desc: CapturedParamDesc): Boolean
}
@@ -237,7 +244,24 @@ class PsiExpressionLambda(
override val invokeMethod: Method
override val invokeMethodDescriptor: FunctionDescriptor
val invokeMethodDescriptor: FunctionDescriptor
override val invokeMethodParameters: List<KotlinType?>
get() {
val actualInvokeDescriptor = if (isSuspend)
getOrCreateJvmSuspendFunctionView(
invokeMethodDescriptor,
languageVersionSettings.isReleaseCoroutines(),
typeMapper.bindingContext
)
else
invokeMethodDescriptor
val valueParameters = actualInvokeDescriptor.valueParameters.map { it.returnType }
return actualInvokeDescriptor.extensionReceiverParameter?.let { listOf(it.returnType) + valueParameters } ?: valueParameters
}
override val invokeMethodReturnType: KotlinType?
get() = invokeMethodDescriptor.returnType
val classDescriptor: ClassDescriptor
@@ -325,14 +349,6 @@ class PsiExpressionLambda(
val isPropertyReference: Boolean
get() = propertyReferenceInfo != null
override fun getInlineSuspendLambdaViewDescriptor(): FunctionDescriptor {
return getOrCreateJvmSuspendFunctionView(
invokeMethodDescriptor,
languageVersionSettings.isReleaseCoroutines(),
typeMapper.bindingContext
)
}
override fun isCapturedSuspend(desc: CapturedParamDesc): Boolean =
isCapturedSuspendLambda(closure, desc.fieldName, typeMapper.bindingContext)
}

View File

@@ -23,13 +23,13 @@ import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsn
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.SmartSet
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -233,38 +233,24 @@ class MethodInliner(
return
}
// in case of inlining suspend lambda reference as ordinary parameter of inline function:
// suspend fun foo (...) ...
// inline fun inlineMe(c: (...) -> ...) ...
// builder {
// inlineMe(::foo)
// }
// we should create additional parameter for continuation.
val valueParameters = info.invokeMethodParameters
// If suspend lambda has no continuation at the end, add it here. (In the IR backend, suspend lambdas
// always come pre-lowered with the continuation parameter.)
var coroutineDesc = desc
val actualInvokeDescriptor: FunctionDescriptor
if (info.isSuspend) {
actualInvokeDescriptor = (info as ExpressionLambda).getInlineSuspendLambdaViewDescriptor()
val parametersSize = actualInvokeDescriptor.valueParameters.size +
(if (actualInvokeDescriptor.extensionReceiverParameter != null) 1 else 0)
// And here we expect invoke(...Ljava/lang/Object;) be replaced with invoke(...Lkotlin/coroutines/Continuation;)
// if this does not happen, insert fake continuation, since we could not have one yet.
if (!inliningContext.root.state.isIrBackend && info.isSuspend) {
val argumentTypes = Type.getArgumentTypes(desc)
if (argumentTypes.size != parametersSize &&
// But do not add it in IR. In IR we already have lowered lambdas with additional parameter, while in Old BE we don't.
!inliningContext.root.state.isIrBackend
) {
if (argumentTypes.size != valueParameters.size) {
addFakeContinuationMarker(this)
coroutineDesc = Type.getMethodDescriptor(Type.getReturnType(desc), *argumentTypes, AsmTypes.OBJECT_TYPE)
}
} else {
actualInvokeDescriptor = info.invokeMethodDescriptor
}
val valueParameters =
listOfNotNull(actualInvokeDescriptor.extensionReceiverParameter) + actualInvokeDescriptor.valueParameters
val erasedInvokeFunction = ClosureCodegen.getErasedInvokeFunction(actualInvokeDescriptor)
val invokeParameters = erasedInvokeFunction.valueParameters
// TODO: this is a weird way to get N instances of `Any?`
val moduleBuiltIns = inliningContext.root.sourceCompilerForInline.compilationContextDescriptor.builtIns
val erasedFunctionType = moduleBuiltIns.getFunction(valueParameters.size).defaultType
val erasedInvokeFunction = erasedFunctionType.memberScope
.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND).first()
val invokeParameters = erasedInvokeFunction.valueParameters.map { it.returnType }
val valueParamShift = max(nextLocalIndex, markerShift)//NB: don't inline cause it changes
val parameterTypesFromDesc = info.invokeMethod.argumentTypes
@@ -305,7 +291,7 @@ class MethodInliner(
result.reifiedTypeParametersUsages.mergeAll(lambdaResult.reifiedTypeParametersUsages)
StackValue
.onStack(info.invokeMethod.returnType, info.invokeMethodDescriptor.returnType)
.onStack(info.invokeMethod.returnType, info.invokeMethodReturnType)
.put(OBJECT_TYPE, erasedInvokeFunction.returnType, this)
setLambdaInlining(false)
addInlineMarker(this, false)
@@ -1075,8 +1061,8 @@ class MethodInliner(
private fun putStackValuesIntoLocalsForLambdaOnInvoke(
directOrder: List<Type>,
directOrderOfArguments: List<ParameterDescriptor>,
directOrderOfInvokeParameters: List<ValueParameterDescriptor>,
directOrderOfArguments: List<KotlinType?>,
directOrderOfInvokeParameters: List<KotlinType?>,
shift: Int,
iv: InstructionAdapter,
descriptor: String
@@ -1099,8 +1085,8 @@ class MethodInliner(
val argumentKotlinType: KotlinType?
val invokeParameterKotlinType: KotlinType?
if (safeToUseArgumentKotlinType) {
argumentKotlinType = directOrderOfArguments[index].type
invokeParameterKotlinType = directOrderOfInvokeParameters[index].type
argumentKotlinType = directOrderOfArguments[index]
invokeParameterKotlinType = directOrderOfInvokeParameters[index]
} else {
argumentKotlinType = null
invokeParameterKotlinType = null

View File

@@ -53,6 +53,7 @@ public class Usage {
appendln(sb, "Advanced options are non-standard and may be changed or removed without any notice.");
}
else {
renderOptionJUsage(sb);
renderArgfileUsage(sb);
}
@@ -103,6 +104,15 @@ public class Usage {
appendln(sb, argument.description().replace("\n", "\n" + StringsKt.repeat(" ", OPTION_NAME_PADDING_WIDTH)));
}
private static void renderOptionJUsage(@NotNull StringBuilder sb) {
int descriptionStart = sb.length() + OPTION_NAME_PADDING_WIDTH;
sb.append(" -J<option>");
while (sb.length() < descriptionStart) {
sb.append(" ");
}
appendln(sb, "Pass an option directly to JVM");
}
private static void renderArgfileUsage(@NotNull StringBuilder sb) {
int descriptionStart = sb.length() + OPTION_NAME_PADDING_WIDTH;
sb.append(" ");

View File

@@ -0,0 +1,30 @@
FILE: capturedTypeInEquality.kt
public abstract interface FirTargetElement : R|kotlin/Any| {
}
public abstract interface FirFunction<F : R|FirFunction<F>|> : R|FirTargetElement| {
}
public abstract interface FirPropertyAccessor : R|FirFunction<FirPropertyAccessor>| {
}
public abstract interface FirProperty : R|kotlin/Any| {
public abstract val getter: R|FirPropertyAccessor|
public get(): R|FirPropertyAccessor|
}
public abstract interface FirTarget<E : R|FirTargetElement|> : R|kotlin/Any| {
public abstract val labeledElement: R|E|
public get(): R|E|
}
public final fun foo(target: R|FirTarget<FirFunction<*>>|, property: R|FirProperty|): R|kotlin/Unit| {
lval functionTarget: R|FirFunction<*>| = R|<local>/target|.R|SubstitutionOverride</FirTarget.labeledElement: R|FirFunction<*>|>|
lval x: R|kotlin/Int?| = (R|<local>/functionTarget| as? R|FirFunction<CapturedType(*)>|)?.{ $subj$.R|kotlin/let|<R|FirFunction<*>|, R|kotlin/Int|>(<L> = let@fun <anonymous>(it: R|FirFunction<*>|): R|kotlin/Int| <inline=Inline, kind=EXACTLY_ONCE> {
when () {
===(R|<local>/property|.R|/FirProperty.getter|, R|<local>/functionTarget|) -> {
^@let Int(1)
}
}
^ Int(0)
}
) }
}

View File

@@ -0,0 +1,23 @@
interface FirTargetElement
interface FirFunction<F : FirFunction<F>> : FirTargetElement
interface FirPropertyAccessor : FirFunction<FirPropertyAccessor>
interface FirProperty {
val getter: FirPropertyAccessor
}
interface FirTarget<E : FirTargetElement> {
val labeledElement: E
}
fun foo(target: FirTarget<FirFunction<*>>, property: FirProperty) {
val functionTarget = target.labeledElement
val x = (functionTarget as? FirFunction)?.let {
if (<!EQUALITY_NOT_APPLICABLE_WARNING!>property.getter === functionTarget<!>) {
return@let 1
}
0
}
}

View File

@@ -5293,6 +5293,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("capturedTypeInEquality.kt")
public void testCapturedTypeInEquality() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/capturedTypeInEquality.kt");
}
@Test
@TestMetadata("DeepCopyIrTree.kt")
public void testDeepCopyIrTree() throws Exception {

View File

@@ -5293,6 +5293,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("capturedTypeInEquality.kt")
public void testCapturedTypeInEquality() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/capturedTypeInEquality.kt");
}
@Test
@TestMetadata("DeepCopyIrTree.kt")
public void testDeepCopyIrTree() throws Exception {

View File

@@ -12395,6 +12395,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/inference/kt40396.kt");
}
@Test
@TestMetadata("kt46515.kt")
public void testKt46515() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/kt46515.kt");
}
@Test
@TestMetadata("kt6175.kt")
public void testKt6175() throws Exception {

View File

@@ -12395,6 +12395,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/inference/kt40396.kt");
}
@Test
@TestMetadata("kt46515.kt")
public void testKt46515() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/kt46515.kt");
}
@Test
@TestMetadata("kt6175.kt")
public void testKt6175() throws Exception {

View File

@@ -605,6 +605,9 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val UNINITIALIZED_VARIABLE by error<KtSimpleNameExpression> {
parameter<FirPropertySymbol>("variable")
}
val UNINITIALIZED_PARAMETER by error<KtSimpleNameExpression> {
parameter<FirVariableSymbol<FirValueParameter>>("parameter")
}
val UNINITIALIZED_ENUM_ENTRY by error<KtSimpleNameExpression> {
parameter<FirVariableSymbol<FirEnumEntry>>("enumEntry")
}

View File

@@ -370,6 +370,7 @@ object FirErrors {
// Control flow diagnostics
val UNINITIALIZED_VARIABLE by error1<KtSimpleNameExpression, FirPropertySymbol>()
val UNINITIALIZED_PARAMETER by error1<KtSimpleNameExpression, FirVariableSymbol<FirValueParameter>>()
val UNINITIALIZED_ENUM_ENTRY by error1<KtSimpleNameExpression, FirVariableSymbol<FirEnumEntry>>()
val UNINITIALIZED_ENUM_COMPANION by error1<KtSimpleNameExpression, FirRegularClassSymbol>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val VAL_REASSIGNMENT by error1<KtExpression, FirVariableSymbol<*>>()

View File

@@ -27,10 +27,7 @@ import org.jetbrains.kotlin.fir.resolve.dfa.cfg.JumpNode
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.intersectTypesOrNull
import org.jetbrains.kotlin.fir.types.isNullable
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.utils.addIfNotNull
@@ -56,7 +53,7 @@ object FirReturnsImpliesAnalyzer : FirControlFlowChecker() {
throw IllegalStateException("Update of all receivers is not possible for this logic system")
override fun ConeKotlinType.isAcceptableForSmartcast(): Boolean {
return true
return !isNullableNothing
}
}

View File

@@ -234,7 +234,8 @@ internal object ConeTypeCompatibilityChecker {
is ConeDefinitelyNotNullType -> original.collectUpperBounds()
is ConeIntersectionType -> intersectedTypes.flatMap { it.collectUpperBounds() }.toSet()
is ConeFlexibleType -> upperBound.collectUpperBounds()
is ConeCapturedType, is ConeStubType, is ConeIntegerLiteralType -> throw IllegalStateException("$this should not reach here")
is ConeCapturedType -> constructor.supertypes?.flatMap { it.collectUpperBounds() }?.toSet().orEmpty()
is ConeStubType, is ConeIntegerLiteralType -> throw IllegalStateException("$this should not reach here")
}
}
@@ -256,7 +257,8 @@ internal object ConeTypeCompatibilityChecker {
is ConeDefinitelyNotNullType -> original.collectLowerBounds()
is ConeIntersectionType -> intersectedTypes.flatMap { it.collectLowerBounds() }.toSet()
is ConeFlexibleType -> lowerBound.collectLowerBounds()
is ConeCapturedType, is ConeStubType, is ConeIntegerLiteralType -> throw IllegalStateException("$this should not reach here")
is ConeCapturedType -> constructor.supertypes?.flatMap { it.collectLowerBounds() }?.toSet().orEmpty()
is ConeStubType, is ConeIntegerLiteralType -> throw IllegalStateException("$this should not reach here")
}
}

View File

@@ -9,21 +9,18 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSymbolOwner
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.modalityModifier
import org.jetbrains.kotlin.fir.analysis.diagnostics.overrideModifier
import org.jetbrains.kotlin.fir.analysis.diagnostics.visibilityModifier
import org.jetbrains.kotlin.fir.analysis.getChild
import org.jetbrains.kotlin.fir.containingClass
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirComponentCall
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.SessionHolder
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
import org.jetbrains.kotlin.fir.resolve.symbolProvider
@@ -32,11 +29,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
@@ -49,6 +42,8 @@ import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeCheckerProviderContext
import org.jetbrains.kotlin.util.ImplementationStatus
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
private val INLINE_ONLY_ANNOTATION_CLASS_ID = ClassId.topLevel(FqName("kotlin.internal.InlineOnly"))
@@ -293,16 +288,6 @@ fun FirClass<*>.findNonInterfaceSupertype(context: CheckerContext): FirTypeRef?
return null
}
/**
* Returns KtModifierToken by Modality
*/
fun Modality.toToken(): KtModifierKeywordToken = when (this) {
Modality.FINAL -> KtTokens.FINAL_KEYWORD
Modality.SEALED -> KtTokens.SEALED_KEYWORD
Modality.OPEN -> KtTokens.OPEN_KEYWORD
Modality.ABSTRACT -> KtTokens.ABSTRACT_KEYWORD
}
val FirFunctionCall.isIterator
get() = this.calleeReference.name.asString() == "<iterator>"
@@ -397,15 +382,16 @@ private fun lowerThanBound(context: ConeInferenceContext, argument: ConeKotlinTy
fun FirMemberDeclaration.isInlineOnly(): Boolean = isInline && hasAnnotation(INLINE_ONLY_ANNOTATION_CLASS_ID)
val FirExpression.isComponentCall
get() = this is FirComponentCall
fun isSubtypeForTypeMismatch(context: ConeInferenceContext, subtype: ConeKotlinType, supertype: ConeKotlinType): Boolean {
return AbstractTypeChecker.isSubtypeOf(context, subtype, supertype)
|| isSubtypeOfForFunctionalTypeReturningUnit(context.session.typeContext, subtype, supertype)
}
fun isSubtypeOfForFunctionalTypeReturningUnit(context: ConeInferenceContext, subtype: ConeKotlinType, supertype: ConeKotlinType): Boolean {
private fun isSubtypeOfForFunctionalTypeReturningUnit(
context: ConeInferenceContext,
subtype: ConeKotlinType,
supertype: ConeKotlinType
): Boolean {
if (!supertype.isBuiltinFunctionalType(context.session)) return false
val functionalTypeReturnType = supertype.typeArguments.lastOrNull()
if ((functionalTypeReturnType as? ConeClassLikeType)?.isUnit == true) {
@@ -428,3 +414,107 @@ fun isSubtypeOfForFunctionalTypeReturningUnit(context: ConeInferenceContext, sub
}
return false
}
fun FirCallableMemberDeclaration<*>.isVisibleInClass(parentClass: FirClass<*>): Boolean {
val classPackage = parentClass.symbol.classId.packageFqName
if (visibility == Visibilities.Private ||
!visibility.visibleFromPackage(classPackage, symbol.callableId.packageName)
) return false
if (visibility == Visibilities.Internal &&
declarationSiteSession !== parentClass.declarationSiteSession
) return false
return true
}
/**
* Get the [ImplementationStatus] for this member.
*
* @param parentClass the contextual class for this query.
*/
fun FirCallableMemberDeclaration<*>.getImplementationStatus(sessionHolder: SessionHolder, parentClass: FirClass<*>): ImplementationStatus {
val containingClass = getContainingClass(sessionHolder)
val symbol = this.symbol
if (symbol is FirIntersectionCallableSymbol) {
if (containingClass === parentClass && symbol.subjectToManyNotImplemented(sessionHolder)) {
return ImplementationStatus.AMBIGUOUSLY_INHERITED
}
// In Java 8, non-abstract intersection overrides having abstract symbol from base class
// still should be implemented in current class (even when they have default interface implementation)
if (symbol.intersections.any {
val fir = (it.fir as FirCallableMemberDeclaration).unwrapFakeOverrides()
fir.isAbstract && (fir.getContainingClass(sessionHolder) as? FirRegularClass)?.classKind == ClassKind.CLASS
}
) {
// Exception from the rule above: interface implementation via delegation
if (symbol.intersections.none {
val fir = (it.fir as FirCallableMemberDeclaration)
fir.origin == FirDeclarationOrigin.Delegated && !fir.isAbstract
}
) {
return ImplementationStatus.NOT_IMPLEMENTED
}
}
}
if (this is FirSimpleFunction) {
if (parentClass is FirRegularClass && parentClass.isData && matchesDataClassSyntheticMemberSignatures) {
return ImplementationStatus.INHERITED_OR_SYNTHESIZED
}
// TODO: suspend function overridden by a Java class in the middle is not properly regarded as an override
if (isSuspend) {
return ImplementationStatus.INHERITED_OR_SYNTHESIZED
}
}
return when {
isFinal -> ImplementationStatus.CANNOT_BE_IMPLEMENTED
containingClass === parentClass && origin == FirDeclarationOrigin.Source -> ImplementationStatus.ALREADY_IMPLEMENTED
containingClass is FirRegularClass && containingClass.isExpect -> ImplementationStatus.CANNOT_BE_IMPLEMENTED
isAbstract -> ImplementationStatus.NOT_IMPLEMENTED
else -> ImplementationStatus.INHERITED_OR_SYNTHESIZED
}
}
private fun FirIntersectionCallableSymbol.subjectToManyNotImplemented(sessionHolder: SessionHolder): Boolean {
var nonAbstractCountInClass = 0
var nonAbstractCountInInterface = 0
var abstractCountInInterface = 0
for (intersectionSymbol in intersections) {
val intersection = intersectionSymbol.fir as FirCallableMemberDeclaration
val containingClass = intersection.getContainingClass(sessionHolder) as? FirRegularClass
val hasInterfaceContainer = containingClass?.classKind == ClassKind.INTERFACE
if (intersection.modality != Modality.ABSTRACT) {
if (hasInterfaceContainer) {
nonAbstractCountInInterface++
} else {
nonAbstractCountInClass++
}
} else if (hasInterfaceContainer) {
abstractCountInInterface++
}
if (nonAbstractCountInClass + nonAbstractCountInInterface > 1) {
return true
}
if (nonAbstractCountInInterface > 0 && abstractCountInInterface > 0) {
return true
}
}
return false
}
private val FirSimpleFunction.matchesDataClassSyntheticMemberSignatures: Boolean
get() = (this.name == OperatorNameConventions.EQUALS && matchesEqualsSignature) ||
(this.name == HASHCODE_NAME && matchesHashCodeSignature) ||
(this.name == OperatorNameConventions.TO_STRING && matchesToStringSignature)
private fun FirSymbolOwner<*>.getContainingClass(sessionHolder: SessionHolder): FirClassLikeDeclaration<*>? =
this.safeAs<FirCallableMemberDeclaration<*>>()?.containingClass()?.toSymbol(sessionHolder.session)?.fir
// NB: we intentionally do not check return types
private val FirSimpleFunction.matchesEqualsSignature: Boolean
get() = valueParameters.size == 1 && valueParameters[0].returnTypeRef.coneType.isNullableAny
private val FirSimpleFunction.matchesHashCodeSignature: Boolean
get() = valueParameters.isEmpty()
private val FirSimpleFunction.matchesToStringSignature: Boolean
get() = valueParameters.isEmpty()

View File

@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirRealSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.isInline
@@ -12,19 +13,24 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOnWithSuppression
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
import org.jetbrains.kotlin.fir.types.arrayElementType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.isUnsignedTypeOrNullableUnsignedType
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.types.AbstractTypeChecker
object FirFunctionParameterChecker : FirFunctionChecker() {
override fun check(declaration: FirFunction<*>, context: CheckerContext, reporter: DiagnosticReporter) {
checkVarargParameters(declaration, context, reporter)
checkParameterTypes(declaration, context, reporter)
checkUninitializedParameter(declaration, context, reporter)
}
private fun checkParameterTypes(declaration: FirFunction<*>, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -70,4 +76,33 @@ object FirFunctionParameterChecker : FirFunctionChecker() {
}
}
}
private fun checkUninitializedParameter(function: FirFunction<*>, context: CheckerContext, reporter: DiagnosticReporter) {
for ((index, parameter) in function.valueParameters.withIndex()) {
// Alas, CheckerContext.qualifiedAccesses stack is not available at this point.
// Thus, manually visit default value expression and report the diagnostic on qualified accesses of interest.
parameter.defaultValue?.accept(object : FirVisitorVoid() {
override fun visitElement(element: FirElement) {
element.acceptChildren(this)
}
override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression) {
val namedReference = qualifiedAccessExpression.calleeReference as? FirResolvedNamedReference ?: return
val referredParameter = namedReference.resolvedSymbol.fir as? FirValueParameter ?: return
val referredParameterIndex = function.valueParameters.indexOf(referredParameter)
// Skip if the referred parameter is not declared in the same function.
if (referredParameterIndex < 0) return
if (index <= referredParameterIndex) {
reporter.reportOnWithSuppression(
qualifiedAccessExpression,
FirErrors.UNINITIALIZED_PARAMETER,
referredParameter.symbol,
context
)
}
}
})
}
}
}

View File

@@ -8,13 +8,13 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.FirRealSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.isComponentCall
import org.jetbrains.kotlin.fir.analysis.checkers.isSubtypeForTypeMismatch
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INITIALIZER_TYPE_MISMATCH
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.expressions.FirComponentCall
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
@@ -25,7 +25,7 @@ object FirInitializerTypeMismatchChecker : FirPropertyChecker() {
val initializer = declaration.initializer ?: return
val source = declaration.source ?: return
if (source.elementType == KtNodeTypes.DESTRUCTURING_DECLARATION) return
if (initializer.isComponentCall) return
if (initializer is FirComponentCall) return
if (declaration.returnTypeRef.source?.kind != FirRealSourceElementKind) return
val propertyType = declaration.returnTypeRef.coneType
val expressionType = initializer.typeRef.coneTypeSafe<ConeKotlinType>() ?: return

View File

@@ -8,12 +8,9 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass
import org.jetbrains.kotlin.fir.analysis.checkers.modality
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_MEMBER_NOT_IMPLEMENTED
@@ -24,15 +21,14 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_IMPL_MEMBER_
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERRIDING_FINAL_MEMBER_BY_DELEGATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.containingClass
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverrideFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverridePropertySymbol
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.isNullableAny
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.fir.unwrapFakeOverrides
import org.jetbrains.kotlin.util.ImplementationStatus
object FirNotImplementedOverrideChecker : FirClassChecker() {
@@ -51,115 +47,24 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
val notImplementedSymbols = mutableListOf<FirCallableSymbol<*>>()
val notImplementedIntersectionSymbols = mutableListOf<FirCallableSymbol<*>>()
val invisibleSymbols = mutableListOf<FirCallableSymbol<*>>()
val classPackage = declaration.symbol.classId.packageFqName
fun FirCallableMemberDeclaration<*>.isInvisible(): Boolean {
if (visibility == Visibilities.Private ||
!visibility.visibleFromPackage(classPackage, symbol.callableId.packageName)
) return true
if (visibility == Visibilities.Internal &&
declarationSiteSession !== declaration.declarationSiteSession
) return true
return false
}
fun FirIntersectionCallableSymbol.subjectToManyNotImplemented(): Boolean {
var nonAbstractCountInClass = 0
var nonAbstractCountInInterface = 0
var abstractCountInInterface = 0
for (intersectionSymbol in intersections) {
val intersection = intersectionSymbol.fir as FirCallableMemberDeclaration
val containingClass = intersection.getContainingClass(context) as? FirRegularClass
val hasInterfaceContainer = containingClass?.classKind == ClassKind.INTERFACE
if (intersection.modality != Modality.ABSTRACT) {
if (hasInterfaceContainer) {
nonAbstractCountInInterface++
} else {
nonAbstractCountInClass++
}
} else if (hasInterfaceContainer) {
abstractCountInInterface++
fun collectSymbol(symbol: FirCallableSymbol<*>) {
val fir = symbol.fir as? FirCallableMemberDeclaration<*> ?: return
when (fir.getImplementationStatus(context.sessionHolder, declaration)) {
ImplementationStatus.AMBIGUOUSLY_INHERITED -> notImplementedIntersectionSymbols.add(symbol)
ImplementationStatus.NOT_IMPLEMENTED -> when {
fir.isVisibleInClass(declaration) -> notImplementedSymbols.add(symbol)
else -> invisibleSymbols.add(symbol)
}
if (nonAbstractCountInClass + nonAbstractCountInInterface > 1) {
return true
}
if (nonAbstractCountInInterface > 0 && abstractCountInInterface > 0) {
return true
else -> {
// nothing to do
}
}
return false
}
fun FirIntersectionCallableSymbol.shouldBeImplemented(): Boolean {
// In Java 8, non-abstract intersection overrides having abstract symbol from base class
// still should be implemented in current class (even when they have default interface implementation)
if (intersections.none {
val fir = (it.fir as FirCallableMemberDeclaration).unwrapFakeOverrides()
fir.isAbstract && (fir.getContainingClass(context) as? FirRegularClass)?.classKind == ClassKind.CLASS
}
) return false
// Exception from the rule above: interface implementation via delegation
if (intersections.any {
val fir = (it.fir as FirCallableMemberDeclaration)
fir.origin == FirDeclarationOrigin.Delegated && !fir.isAbstract
}
) return false
return true
}
fun FirCallableMemberDeclaration<*>.shouldBeImplemented(): Boolean {
val containingClass = getContainingClass(context)
if (containingClass is FirRegularClass && containingClass.isExpect) return false
if (!isAbstract) {
val symbol = symbol as? FirIntersectionCallableSymbol ?: return false
return symbol.shouldBeImplemented()
}
if (containingClass === declaration && origin == FirDeclarationOrigin.Source) return false
return true
}
for (name in classScope.getCallableNames()) {
classScope.processFunctionsByName(name) { namedFunctionSymbol ->
val simpleFunction = namedFunctionSymbol.fir
if (namedFunctionSymbol is FirIntersectionOverrideFunctionSymbol) {
if (simpleFunction.getContainingClass(context) === declaration &&
namedFunctionSymbol.subjectToManyNotImplemented()
) {
notImplementedIntersectionSymbols += namedFunctionSymbol
return@processFunctionsByName
}
}
if (!simpleFunction.shouldBeImplemented()) return@processFunctionsByName
if (declaration is FirRegularClass && declaration.isData && simpleFunction.matchesDataClassSyntheticMemberSignatures) {
return@processFunctionsByName
}
// TODO: suspend function overridden by a Java class in the middle is not properly regarded as an override
if (simpleFunction.isSuspend) return@processFunctionsByName
if (simpleFunction.isInvisible()) {
invisibleSymbols += namedFunctionSymbol
} else {
notImplementedSymbols += namedFunctionSymbol
}
}
classScope.processPropertiesByName(name) { propertySymbol ->
val property = propertySymbol.fir as? FirProperty ?: return@processPropertiesByName
if (propertySymbol is FirIntersectionOverridePropertySymbol) {
if (property.getContainingClass(context) === declaration &&
propertySymbol.subjectToManyNotImplemented()
) {
notImplementedIntersectionSymbols += propertySymbol
return@processPropertiesByName
}
}
if (!property.shouldBeImplemented()) return@processPropertiesByName
if (property.isInvisible()) {
invisibleSymbols += propertySymbol
} else {
notImplementedSymbols += propertySymbol
}
}
classScope.processFunctionsByName(name, ::collectSymbol)
classScope.processPropertiesByName(name, ::collectSymbol)
}
if (notImplementedSymbols.isNotEmpty()) {
@@ -237,19 +142,4 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
private fun FirCallableDeclaration<*>.isFromInterfaceOrEnum(context: CheckerContext): Boolean =
(getContainingClass(context) as? FirRegularClass)?.let { it.isInterface || it.isEnumClass } == true
private val FirSimpleFunction.matchesDataClassSyntheticMemberSignatures: Boolean
get() = (this.name == OperatorNameConventions.EQUALS && matchesEqualsSignature) ||
(this.name == HASHCODE_NAME && matchesHashCodeSignature) ||
(this.name == OperatorNameConventions.TO_STRING && matchesToStringSignature)
// NB: we intentionally do not check return types
private val FirSimpleFunction.matchesEqualsSignature: Boolean
get() = valueParameters.size == 1 && valueParameters[0].returnTypeRef.coneType.isNullableAny
private val FirSimpleFunction.matchesHashCodeSignature: Boolean
get() = valueParameters.isEmpty()
private val FirSimpleFunction.matchesToStringSignature: Boolean
get() = valueParameters.isEmpty()
}

View File

@@ -17,6 +17,8 @@ import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.analysis.checkers.ConeTypeCompatibilityChecker.areCompatible
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.render
object FirEqualityCompatibilityChecker : FirEqualityOperatorCallChecker() {
override fun check(expression: FirEqualityOperatorCall, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -30,7 +32,16 @@ object FirEqualityCompatibilityChecker : FirEqualityOperatorCallChecker() {
val inferenceContext = context.session.inferenceComponents.ctx
val intersectionType = inferenceContext.intersectTypesOrNull(listOf(lType, rType)) as? ConeIntersectionType ?: return
val compatibility = intersectionType.intersectedTypes.areCompatible(inferenceContext)
val compatibility = try {
intersectionType.intersectedTypes.areCompatible(inferenceContext)
} catch (e: Throwable) {
throw IllegalStateException(
"Exception while determining type compatibility: type ${intersectionType.render()}, " +
"equality ${expression.render()}, " +
"file ${context.containingDeclarations.filterIsInstance<FirFile>().firstOrNull()?.name}",
e
)
}
if (compatibility != ConeTypeCompatibilityChecker.Compatibility.COMPATIBLE) {
when (expression.source?.kind) {
FirRealSourceElementKind -> {

View File

@@ -271,6 +271,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_ON
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNEXPECTED_SAFE_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_ENUM_COMPANION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_ENUM_ENTRY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_VARIABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_LATEINIT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_NOT_NULL_ASSERTION
@@ -830,7 +831,8 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
)
// Control flow diagnostics
map.put(UNINITIALIZED_VARIABLE, "{0} must be initialized before access", VARIABLE_NAME)
map.put(UNINITIALIZED_VARIABLE, "Variable ''{0}'' must be initialized", VARIABLE_NAME)
map.put(UNINITIALIZED_PARAMETER, "Parameter ''{0}'' is uninitialized here", VARIABLE_NAME)
map.put(UNINITIALIZED_ENUM_ENTRY, "Enum entry ''{0}'' is uninitialized here", VARIABLE_NAME)
map.put(UNINITIALIZED_ENUM_COMPANION, "Companion object of enum class ''{0}'' is uninitialized here", SYMBOL)
map.put(VAL_REASSIGNMENT, "Val cannot be reassigned", VARIABLE_NAME)

View File

@@ -59,6 +59,7 @@ if (kotlinBuildProperties.isInJpsBuildIdeaSync) {
}
projectTest(jUnit5Enabled = true) {
dependsOn(":dist")
workingDir = rootDir
useJUnitPlatform()
}

View File

@@ -95,21 +95,20 @@ class Fir2IrConversionScope {
}
fun returnTarget(expression: FirReturnExpression, declarationStorage: Fir2IrDeclarationStorage): IrFunction {
val firTarget = expression.target.labeledElement
val irTarget = (firTarget as? FirFunction)?.let {
when (it) {
is FirConstructor -> declarationStorage.getCachedIrConstructor(it)
is FirPropertyAccessor -> {
for ((property, firProperty) in propertyStack.asReversed()) {
if (firProperty?.getter === firTarget) {
return@let property.getter
} else if (firProperty?.setter === firTarget) {
return@let property.setter
}
val irTarget = when (val firTarget = expression.target.labeledElement) {
is FirConstructor -> declarationStorage.getCachedIrConstructor(firTarget)
is FirPropertyAccessor -> {
var answer: IrFunction? = null
for ((property, firProperty) in propertyStack.asReversed()) {
if (firProperty?.getter === firTarget) {
answer = property.getter
} else if (firProperty?.setter === firTarget) {
answer = property.setter
}
}
else -> declarationStorage.getCachedIrFunction(it)
answer
}
else -> declarationStorage.getCachedIrFunction(firTarget)
}
for (potentialTarget in functionStack.asReversed()) {
if (potentialTarget == irTarget) {

View File

@@ -277,6 +277,14 @@ class Fir2IrImplicitCastInserter(
return implicitCastOrExpression(data as IrExpression, expressionWithSmartcast.typeRef)
}
override fun visitExpressionWithSmartcastToNull(
expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull,
data: IrElement
): IrElement {
// We don't want an implicit cast to Nothing?. This expression just encompasses nullability after null check.
return data
}
internal fun implicitCastFromDispatchReceiver(
original: IrExpression,
originalTypeRef: FirTypeRef,

View File

@@ -420,6 +420,14 @@ class Fir2IrVisitor(
return implicitCastInserter.visitExpressionWithSmartcast(expressionWithSmartcast, value)
}
override fun visitExpressionWithSmartcastToNull(
expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull,
data: Any?
): IrElement {
// This should not be materialized. Generate the expression with the original expression.
return convertToIrExpression(expressionWithSmartcastToNull.originalExpression)
}
override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: Any?): IrElement {
val explicitReceiverExpression = convertToIrReceiverExpression(
callableReferenceAccess.explicitReceiver, callableReferenceAccess.calleeReference, callableReferenceAccess

View File

@@ -429,6 +429,24 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/annotations/typeAnnotations/checkingNotincorporatedInputTypes.kt");
}
@Test
@TestMetadata("classTypeParameterBound.kt")
public void testClassTypeParameterBound() throws Exception {
runTest("compiler/testData/codegen/box/annotations/typeAnnotations/classTypeParameterBound.kt");
}
@Test
@TestMetadata("classTypeParameterBoundsJava.kt")
public void testClassTypeParameterBoundsJava() throws Exception {
runTest("compiler/testData/codegen/box/annotations/typeAnnotations/classTypeParameterBoundsJava.kt");
}
@Test
@TestMetadata("functionTypeParameterBound.kt")
public void testFunctionTypeParameterBound() throws Exception {
runTest("compiler/testData/codegen/box/annotations/typeAnnotations/functionTypeParameterBound.kt");
}
@Test
@TestMetadata("implicitReturn.kt")
public void testImplicitReturn() throws Exception {
@@ -453,6 +471,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/annotations/typeAnnotations/methodParameters.kt");
}
@Test
@TestMetadata("methodTypeParameters.kt")
public void testMethodTypeParameters() throws Exception {
runTest("compiler/testData/codegen/box/annotations/typeAnnotations/methodTypeParameters.kt");
}
@Test
@TestMetadata("typeAnnotationTarget6.kt")
public void testTypeAnnotationTarget6() throws Exception {
@@ -9060,6 +9084,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/coroutines/iterateOverArray.kt");
}
@Test
@TestMetadata("jvmStaticAndJvmInline.kt")
public void testJvmStaticAndJvmInline() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/jvmStaticAndJvmInline.kt");
}
@Test
@TestMetadata("kt12958.kt")
public void testKt12958() throws Exception {
@@ -15686,6 +15716,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/funInterface/kt45444_privateFunInterface.kt");
}
@Test
@TestMetadata("kt46512_indyFunInterfaceOverCallableReference.kt")
public void testKt46512_indyFunInterfaceOverCallableReference() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/kt46512_indyFunInterfaceOverCallableReference.kt");
}
@Test
@TestMetadata("multimodule.kt")
public void testMultimodule() throws Exception {
@@ -18970,6 +19006,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/intN.kt");
}
@Test
@TestMetadata("null.kt")
public void testNull() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/null.kt");
}
@Test
@TestMetadata("result.kt")
public void testResult() throws Exception {
@@ -19914,6 +19956,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/funInterface/ifaceChild.kt");
}
@Test
@TestMetadata("nullableResult.kt")
public void testNullableResult() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/funInterface/nullableResult.kt");
}
@Test
@TestMetadata("primitive.kt")
public void testPrimitive() throws Exception {
@@ -19972,6 +20020,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/lambda/ifaceChild.kt");
}
@Test
@TestMetadata("nullableResult.kt")
public void testNullableResult() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/lambda/nullableResult.kt");
}
@Test
@TestMetadata("primitive.kt")
public void testPrimitive() throws Exception {
@@ -20030,6 +20084,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/objectLiteral/ifaceChild.kt");
}
@Test
@TestMetadata("nullableResult.kt")
public void testNullableResult() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/objectLiteral/nullableResult.kt");
}
@Test
@TestMetadata("primitive.kt")
public void testPrimitive() throws Exception {
@@ -20901,6 +20961,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/invokedynamic/sam/samExtFunWithCapturingLambda.kt");
}
@Test
@TestMetadata("serializableSam1.kt")
public void testSerializableSam1() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/serializableSam1.kt");
}
@Test
@TestMetadata("serializableSam2.kt")
public void testSerializableSam2() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/serializableSam2.kt");
}
@Test
@TestMetadata("simpleFunInterfaceConstructor.kt")
public void testSimpleFunInterfaceConstructor() throws Exception {
@@ -24166,6 +24238,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/jvmStatic/kt45408.kt");
}
@Test
@TestMetadata("kt46568.kt")
public void testKt46568() throws Exception {
runTest("compiler/testData/codegen/box/jvmStatic/kt46568.kt");
}
@Test
@TestMetadata("kt9897_static.kt")
public void testKt9897_static() throws Exception {

View File

@@ -3512,6 +3512,12 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/generationOfAccessorToUnderlyingValue.kt");
}
@Test
@TestMetadata("genericNoUnbox.kt")
public void testGenericNoUnbox() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/genericNoUnbox.kt");
}
@Test
@TestMetadata("hashCodeIsCalledByInlineClass.kt")
public void testHashCodeIsCalledByInlineClass() throws Exception {

View File

@@ -1574,7 +1574,7 @@ class DeclarationsConverter(
val delegateName = Name.special("<\$\$delegate_${delegateFields.size}>")
delegateFields.add(
buildField {
source = firExpression!!.source
source = firExpression!!.source?.fakeElement(FirFakeSourceElementKind.ClassDelegationField)
declarationSiteSession = baseSession
origin = FirDeclarationOrigin.Synthetic
name = delegateName

View File

@@ -566,7 +566,8 @@ open class RawFirBuilder(
val delegateExpression = { superTypeListEntry.delegateExpression }.toFirExpression("Should have delegate")
container.superTypeRefs += type
val delegateName = Name.special("<\$\$delegate_${delegateFields.size}>")
val delegateSource = superTypeListEntry.delegateExpression?.toFirSourceElement()
val delegateSource =
superTypeListEntry.delegateExpression?.toFirSourceElement(FirFakeSourceElementKind.ClassDelegationField)
val delegateField = buildField {
source = delegateSource
declarationSiteSession = baseSession

View File

@@ -185,9 +185,12 @@ class FirTowerDataContextsForClassParts(
modeMap[mode] = value
}
fun setAnonymousFunctionContext(symbol: FirAnonymousFunctionSymbol) {
mode = SPECIAL
modeMap[SPECIAL] = towerDataContextForAnonymousFunctions.getValue(symbol)
fun setAnonymousFunctionContextIfAny(symbol: FirAnonymousFunctionSymbol) {
val context = towerDataContextForAnonymousFunctions[symbol]
if (context != null) {
mode = SPECIAL
modeMap[SPECIAL] = context
}
}
fun setCallableReferenceContextIfAny(access: FirCallableReferenceAccess) {

View File

@@ -247,9 +247,35 @@ private fun BodyResolveComponents.typeFromSymbol(symbol: AbstractFirBasedSymbol<
}
}
fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(qualifiedAccessExpression: FirQualifiedAccessExpression): FirQualifiedAccessExpression {
fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(
qualifiedAccessExpression: FirQualifiedAccessExpression
): FirQualifiedAccessExpression {
val 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.
// TODO: should we differentiate x == null v.s. x is Nothing?
if (typesFromSmartCast.any { it.isNullableNothing }) {
val typesFromSmartcastWithoutNullableNothing =
typesFromSmartCast.filterTo(mutableListOf()) { !it.isNullableNothing }.also {
it += originalType
}
val intersectedTypeWithoutNullableNothing =
ConeTypeIntersector.intersectTypes(session.inferenceComponents.ctx, typesFromSmartcastWithoutNullableNothing)
val intersectedTypeRefWithoutNullableNothing = buildResolvedTypeRef {
source = qualifiedAccessExpression.resultType.source?.fakeElement(FirFakeSourceElementKind.SmartCastedTypeRef)
type = intersectedTypeWithoutNullableNothing
annotations += qualifiedAccessExpression.resultType.annotations
delegatedTypeRef = qualifiedAccessExpression.resultType
}
return buildExpressionWithSmartcastToNull {
originalExpression = qualifiedAccessExpression
// TODO: Use Nothing? during resolution?
typeRef = intersectedTypeRefWithoutNullableNothing
// NB: Nothing? in types from smartcast in DFA is recorded here (and the expression kind itself).
this.typesFromSmartCast = typesFromSmartCast
}
}
val allTypes = typesFromSmartCast.also {
it += originalType
}
@@ -259,6 +285,7 @@ fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(qualifiedAc
source = qualifiedAccessExpression.resultType.source?.fakeElement(FirFakeSourceElementKind.SmartCastedTypeRef)
type = intersectedType
annotations += qualifiedAccessExpression.resultType.annotations
delegatedTypeRef = qualifiedAccessExpression.resultType
}
return buildExpressionWithSmartcast {
originalExpression = qualifiedAccessExpression

View File

@@ -119,9 +119,11 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
}
override fun ConeKotlinType.isAcceptableForSmartcast(): Boolean {
if (this.isNullableNothing) return false
return when (this) {
is ConeClassLikeType -> {
val symbol = fullyExpandedType(components.session).lookupTag.toSymbol(components.session) ?: return false
val symbol =
fullyExpandedType(components.session).lookupTag.toSymbol(components.session) ?: return false
val declaration = symbol.fir as? FirRegularClass ?: return true
visibilityChecker.isVisible(
declaration,
@@ -149,7 +151,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
private var contractDescriptionVisitingMode = false
protected val any = components.session.builtinTypes.anyType.type
private val any = components.session.builtinTypes.anyType.type
private val nullableNothing = components.session.builtinTypes.nullableNothingType.type
@PrivateForInline
@@ -472,11 +474,18 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
) {
val leftIsNullable = leftOperand.coneType.isMarkedNullable
val rightIsNullable = rightOperand.coneType.isMarkedNullable
// left == right && right not null -> left != null
// [processEqNull] adds both implications: operator call could be true or false. We definitely need the matched case only.
fun shouldAddImplicationForStatement(operationStatement: OperationStatement): Boolean {
// Only if operation statement is == True, i.e., left == right
return (operation.isEq() && operationStatement.operation == Operation.EqTrue) ||
(!operation.isEq() && operationStatement.operation == Operation.EqFalse)
}
when {
leftIsNullable && rightIsNullable -> return
leftIsNullable -> processEqNull(node, leftOperand, operation.invert())
rightIsNullable -> processEqNull(node, rightOperand, operation.invert())
leftIsNullable -> processEqNull(node, leftOperand, operation.invert(), ::shouldAddImplicationForStatement)
rightIsNullable -> processEqNull(node, rightOperand, operation.invert(), ::shouldAddImplicationForStatement)
}
if (operation == FirOperation.IDENTITY || operation == FirOperation.NOT_IDENTITY) {
@@ -484,7 +493,25 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
}
}
private fun processEqNull(node: EqualityOperatorCallNode, operand: FirExpression, operation: FirOperation) {
/*
* Process x == null in general: add implications for both cases.
* E.g., say d1 is an eq operator call node, d2 represents `x`, the variable inside the operator call. So, d1: x == null
* This util adds: "d1 == True -> d2 == null" and "d1 == False -> d2 != null"
* so that both branches after the operator call can infer the type of x.
*
* However, users can specify what conditions are of interest.
* E.g., say left == right _and_ right != null, then we can conclude left != null.
* In this example, say d1 is an eq operator call (left == right), and d2 is left.
* Unlike general cases, we want to add: "d1 == True -> d2 != null", and nothing more because the counter part,
* "d1 == False -> d2 == null" doesn't hold. That is, left != right and right != null don't mean left == null. It just means, left is
* something different from right, including null. By filtering "d1 == True" condition only, all the remaining logic can be shared.
*/
private fun processEqNull(
node: EqualityOperatorCallNode,
operand: FirExpression,
operation: FirOperation,
shouldAddImplicationForStatement: (OperationStatement) -> Boolean = { true }
) {
val flow = node.flow
val expressionVariable = variableStorage.createSyntheticVariable(node.fir)
val operandVariable = variableStorage.getOrCreateVariable(node.previousFlow, operand)
@@ -497,20 +524,35 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
}
logicSystem.approveOperationStatement(flow, predicate).forEach { effect ->
flow.addImplication((expressionVariable eq true) implies effect)
flow.addImplication((expressionVariable eq false) implies effect.invert())
if (shouldAddImplicationForStatement(expressionVariable eq true)) {
flow.addImplication((expressionVariable eq true) implies effect)
}
if (shouldAddImplicationForStatement(expressionVariable eq false)) {
flow.addImplication((expressionVariable eq false) implies effect.invert())
}
}
flow.addImplication((expressionVariable eq isEq) implies (operandVariable eq null))
flow.addImplication((expressionVariable notEq isEq) implies (operandVariable notEq null))
if (shouldAddImplicationForStatement(expressionVariable eq isEq)) {
flow.addImplication((expressionVariable eq isEq) implies (operandVariable eq null))
}
if (shouldAddImplicationForStatement(expressionVariable notEq isEq)) {
flow.addImplication((expressionVariable notEq isEq) implies (operandVariable notEq null))
}
if (operandVariable is RealVariable) {
flow.addImplication((expressionVariable eq isEq) implies (operandVariable typeNotEq any))
flow.addImplication((expressionVariable notEq isEq) implies (operandVariable typeEq any))
if (operandVariable.isReal()) {
if (shouldAddImplicationForStatement(expressionVariable eq isEq)) {
flow.addImplication((expressionVariable eq isEq) implies (operandVariable typeNotEq any))
}
if (shouldAddImplicationForStatement(expressionVariable notEq isEq)) {
flow.addImplication((expressionVariable notEq isEq) implies (operandVariable typeEq any))
}
// TODO: design do we need casts to Nothing?
// flow.addImplication((expressionVariable eq !isEq) implies (operandVariable typeEq nullableNothing))
// flow.addImplication((expressionVariable notEq !isEq) implies (operandVariable typeNotEq nullableNothing))
if (shouldAddImplicationForStatement(expressionVariable eq !isEq)) {
flow.addImplication((expressionVariable eq !isEq) implies (operandVariable typeNotEq nullableNothing))
}
if (shouldAddImplicationForStatement(expressionVariable notEq !isEq)) {
flow.addImplication((expressionVariable notEq !isEq) implies (operandVariable typeEq nullableNothing))
}
}
node.flow = flow
}

View File

@@ -42,7 +42,6 @@ class PersistentFlow : Flow {
var logicStatements: PersistentImplications
val level: Int
var approvedTypeStatementsDiff: PersistentApprovedTypeStatements = persistentHashMapOf()
var updatedAliasDiff: PersistentSet<RealVariable> = persistentSetOf()
/*
* val x = a
@@ -204,7 +203,6 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
}
override fun removeLocalVariableAlias(flow: PersistentFlow, alias: RealVariable) {
flow.updatedAliasDiff += alias
val original = flow.directAliasMap[alias]?.variable ?: return
flow.directAliasMap = flow.directAliasMap.remove(alias)
val variables = flow.backwardsAliasMap.getValue(original)
@@ -300,7 +298,6 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
} else {
flow.backwardsAliasMap.put(existedAlias, updatedBackwardsAliasList)
}
flow.updatedAliasDiff = flow.updatedAliasDiff.add(variable)
}
}

View File

@@ -99,7 +99,10 @@ internal val FirElement.symbol: AbstractFirBasedSymbol<*>?
is FirWhenSubjectExpression -> whenRef.value.subject?.symbol
is FirSafeCallExpression -> regularQualifiedAccess.symbol
else -> null
}?.takeIf { this.unwrapSmartcastExpression() is FirThisReceiverExpression || (it !is FirFunctionSymbol<*> && it !is FirAccessorSymbol) }
}?.takeIf {
(this as? FirExpression)?.unwrapSmartcastExpression() is FirThisReceiverExpression ||
(it !is FirFunctionSymbol<*> && it !is FirAccessorSymbol)
}
@DfaInternals
internal val FirResolvable.symbol: AbstractFirBasedSymbol<*>?
@@ -110,4 +113,8 @@ internal val FirResolvable.symbol: AbstractFirBasedSymbol<*>?
else -> null
}
private fun FirElement.unwrapSmartcastExpression(): FirElement = if (this is FirExpressionWithSmartcast) originalExpression else this
internal fun FirExpression.unwrapSmartcastExpression(): FirExpression =
when (this) {
is FirExpressionWithSmartcast -> originalExpression
else -> this
}

View File

@@ -238,7 +238,7 @@ class BodyResolveContext(
return FirMemberTypeParameterScope(this)
}
private fun buildSecondaryConstructorParametersScope(constructor: FirConstructor): FirLocalScope =
fun buildSecondaryConstructorParametersScope(constructor: FirConstructor): FirLocalScope =
constructor.valueParameters.fold(FirLocalScope()) { acc, param -> acc.storeVariable(param) }
@PrivateForInline
@@ -296,7 +296,7 @@ class BodyResolveContext(
@OptIn(PrivateForInline::class)
inline fun <T> withAnonymousFunctionTowerDataContext(symbol: FirAnonymousFunctionSymbol, f: () -> T): T {
return withTowerModeCleanup {
towerDataContextsForClassParts.setAnonymousFunctionContext(symbol)
towerDataContextsForClassParts.setAnonymousFunctionContextIfAny(symbol)
f()
}
}
@@ -486,6 +486,12 @@ class BodyResolveContext(
return withTowerDataCleanup {
addLocalScope(FirLocalScope())
if (function is FirSimpleFunction) {
// Make all value parameters available in the local scope so that even one parameter that refers to another parameter,
// which may not be initialized yet, can be resolved. [FirFunctionParameterChecker] will detect and report an error
// if an uninitialized parameter is accessed by a preceding parameter.
for (parameter in function.valueParameters) {
storeVariable(parameter)
}
val receiverTypeRef = function.receiverTypeRef
withLabelAndReceiverType(function.name, function, receiverTypeRef?.coneType, holder, f)
} else {
@@ -665,19 +671,23 @@ class BodyResolveContext(
f: () -> T
): T {
// Default values of constructor can't access members of constructing class
return withTowerDataMode(FirTowerDataMode.CONSTRUCTOR_HEADER) {
if (!constructor.isPrimary) {
addInaccessibleImplicitReceiverValue(owningClass, holder)
}
withTowerDataCleanup {
addLocalScope(FirLocalScope())
f()
}
}
// But, let them get resolved, then [FirFunctionParameterChecker] will detect and report an error
// if an uninitialized parameter is accessed by a preceding parameter.
return forConstructorParametersOrDelegatedConstructorCall(constructor, owningClass, holder, f)
}
@OptIn(PrivateForInline::class)
fun <T> forDelegatedConstructor(
inline fun <T> forDelegatedConstructorCall(
constructor: FirConstructor,
owningClass: FirRegularClass?,
holder: SessionHolder,
f: () -> T
): T {
return forConstructorParametersOrDelegatedConstructorCall(constructor, owningClass, holder, f)
}
@OptIn(PrivateForInline::class)
inline fun <T> forConstructorParametersOrDelegatedConstructorCall(
constructor: FirConstructor,
owningClass: FirRegularClass?,
holder: SessionHolder,

View File

@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
import org.jetbrains.kotlin.fir.resolve.dfa.FirControlFlowGraphReferenceImpl
import org.jetbrains.kotlin.fir.resolve.dfa.unwrapSmartcastExpression
import org.jetbrains.kotlin.fir.resolve.inference.extractLambdaInfoFromFunctionalType
import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
@@ -594,9 +595,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
ConeSimpleDiagnostic("No type for parameter", DiagnosticKind.ValueParameterWithNoTypeAnnotation)
)
)
return context.withValueParameter(valueParameter) {
valueParameter
}
return valueParameter
}
dataFlowAnalyzer.enterValueParameter(valueParameter)
@@ -795,7 +794,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
if (variable.returnTypeRef is FirImplicitTypeRef) {
val resultType = when {
initializer != null -> {
val unwrappedInitializer = (initializer as? FirExpressionWithSmartcast)?.originalExpression ?: initializer
val unwrappedInitializer = initializer.unwrapSmartcastExpression()
unwrappedInitializer.resultType
}
variable.getter != null && variable.getter !is FirDefaultPropertyAccessor -> variable.getter?.returnTypeRef

View File

@@ -863,7 +863,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
var result = delegatedConstructorCall
try {
val lastDispatchReceiver = implicitReceiverStack.lastDispatchReceiver()
context.forDelegatedConstructor(containingConstructor, containingClass as? FirRegularClass, components) {
context.forDelegatedConstructorCall(containingConstructor, containingClass as? FirRegularClass, components) {
delegatedConstructorCall.transformChildren(transformer, ResolutionMode.ContextDependent)
}

View File

@@ -118,6 +118,13 @@ class ConeEffectExtractor(
return expressionWithSmartcast.originalExpression.accept(this, data)
}
override fun visitExpressionWithSmartcastToNull(
expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull,
data: Nothing?
): ConeContractDescriptionElement? {
return expressionWithSmartcastToNull.originalExpression.accept(this, data)
}
override fun visitQualifiedAccessExpression(
qualifiedAccessExpression: FirQualifiedAccessExpression,
data: Nothing?
@@ -189,4 +196,4 @@ class ConeEffectExtractor(
else -> null
}
}
}
}

View File

@@ -0,0 +1,63 @@
/*
* 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.expressions
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSourceElement
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.fir.visitors.*
import org.jetbrains.kotlin.fir.FirImplementationDetail
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
abstract class FirExpressionWithSmartcastToNull : FirExpressionWithSmartcast() {
abstract override val source: FirSourceElement?
abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotationCall>
abstract override val calleeReference: FirReference
abstract override val typeArguments: List<FirTypeProjection>
abstract override val explicitReceiver: FirExpression?
abstract override val dispatchReceiver: FirExpression
abstract override val extensionReceiver: FirExpression
abstract override val originalExpression: FirQualifiedAccessExpression
abstract override val typesFromSmartCast: Collection<ConeKotlinType>
abstract override val originalType: FirTypeRef
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitExpressionWithSmartcastToNull(this, data)
@Suppress("UNCHECKED_CAST")
override fun <E: FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformExpressionWithSmartcastToNull(this, data) as E
@FirImplementationDetail
abstract override fun replaceSource(newSource: FirSourceElement?)
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract override fun replaceCalleeReference(newCalleeReference: FirReference)
abstract override fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>)
abstract override fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
abstract override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
abstract override fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
abstract override fun <D> transformExplicitReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
abstract override fun <D> transformDispatchReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
abstract override fun <D> transformExtensionReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
}

View File

@@ -91,6 +91,7 @@ import org.jetbrains.kotlin.fir.expressions.FirComponentCall
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
@@ -480,6 +481,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
return transformElement(expressionWithSmartcast, data)
}
open fun transformExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, data: D): FirStatement {
return transformElement(expressionWithSmartcastToNull, data)
}
open fun transformSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: D): FirStatement {
return transformElement(safeCallExpression, data)
}
@@ -980,6 +985,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
return transformExpressionWithSmartcast(expressionWithSmartcast, data)
}
final override fun visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, data: D): FirStatement {
return transformExpressionWithSmartcastToNull(expressionWithSmartcastToNull, data)
}
final override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: D): FirStatement {
return transformSafeCallExpression(safeCallExpression, data)
}

View File

@@ -91,6 +91,7 @@ import org.jetbrains.kotlin.fir.expressions.FirComponentCall
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
@@ -309,6 +310,8 @@ abstract class FirVisitor<out R, in D> {
open fun visitExpressionWithSmartcast(expressionWithSmartcast: FirExpressionWithSmartcast, data: D): R = visitElement(expressionWithSmartcast, data)
open fun visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, data: D): R = visitElement(expressionWithSmartcastToNull, data)
open fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: D): R = visitElement(safeCallExpression, data)
open fun visitCheckedSafeCallSubject(checkedSafeCallSubject: FirCheckedSafeCallSubject, data: D): R = visitElement(checkedSafeCallSubject, data)

View File

@@ -91,6 +91,7 @@ import org.jetbrains.kotlin.fir.expressions.FirComponentCall
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
@@ -479,6 +480,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitElement(expressionWithSmartcast)
}
open fun visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull) {
visitElement(expressionWithSmartcastToNull)
}
open fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression) {
visitElement(safeCallExpression)
}
@@ -979,6 +984,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitExpressionWithSmartcast(expressionWithSmartcast)
}
final override fun visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, data: Nothing?) {
visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull)
}
final override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: Nothing?) {
visitSafeCallExpression(safeCallExpression)
}

View File

@@ -170,6 +170,10 @@ sealed class FirFakeSourceElementKind : FirSourceElementKind() {
// for java annotations constructor implicit parameters are generated
// with a fake source which refers to declared annotation methods
object ImplicitAnnotationAnnotationConstructorParameter : FirFakeSourceElementKind()
// for the implicit field storing the delegated object for class delegation
// with a fake source that refers to the KtExpression that creates the delegate
object ClassDelegationField : FirFakeSourceElementKind()
}
sealed class FirSourceElement {

View File

@@ -57,6 +57,12 @@ inline val FirRegularClass.isFun get() = status.isFun
inline val FirMemberDeclaration.modality get() = status.modality
inline val FirMemberDeclaration.isAbstract get() = status.modality == Modality.ABSTRACT
inline val FirMemberDeclaration.isOpen get() = status.modality == Modality.OPEN
inline val FirMemberDeclaration.isFinal: Boolean
get() {
// member with unspecified modality is final
val modality = status.modality ?: return true
return modality == Modality.FINAL
}
inline val FirMemberDeclaration.visibility: Visibility get() = status.visibility
inline val FirMemberDeclaration.effectiveVisibility: EffectiveVisibility

View File

@@ -50,7 +50,7 @@ inline val FirCall.resolvedArgumentMapping: Map<FirExpression, FirValueParameter
else -> null
}
inline val FirCall.argumentMapping: Map<FirExpression, FirValueParameter>?
inline val FirCall.argumentMapping: LinkedHashMap<FirExpression, FirValueParameter>?
get() = when (val argumentList = argumentList) {
is FirResolvedArgumentList -> argumentList.mapping
is FirPartiallyResolvedArgumentList -> argumentList.mapping

View File

@@ -0,0 +1,26 @@
/*
* 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.expressions.builder
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull
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
class FirExpressionWithSmartcastToNullBuilder {
lateinit var originalExpression: FirQualifiedAccessExpression
lateinit var typeRef: FirTypeRef
lateinit var typesFromSmartCast: Collection<ConeKotlinType>
fun build(): FirExpressionWithSmartcastToNull {
return FirExpressionWithSmartcastToNullImpl(originalExpression, typeRef, typesFromSmartCast)
}
}
inline fun buildExpressionWithSmartcastToNull(init: FirExpressionWithSmartcastToNullBuilder.() -> Unit): FirExpressionWithSmartcastToNull {
return FirExpressionWithSmartcastToNullBuilder().apply(init).build()
}

View File

@@ -0,0 +1,88 @@
/*
* 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.expressions.impl
import org.jetbrains.kotlin.fir.FirImplementationDetail
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeProjection
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
class FirExpressionWithSmartcastToNullImpl(
override var originalExpression: FirQualifiedAccessExpression,
override val typeRef: FirTypeRef,
override val typesFromSmartCast: Collection<ConeKotlinType>
) : FirExpressionWithSmartcastToNull() {
init {
assert(originalExpression.typeRef is FirResolvedTypeRef)
}
override val source: FirSourceElement? get() = originalExpression.source
override val annotations: List<FirAnnotationCall> get() = originalExpression.annotations
override val typeArguments: List<FirTypeProjection> get() = originalExpression.typeArguments
override val explicitReceiver: FirExpression? get() = originalExpression.explicitReceiver
override val dispatchReceiver: FirExpression get() = originalExpression.dispatchReceiver
override val extensionReceiver: FirExpression get() = originalExpression.extensionReceiver
override val calleeReference: FirReference get() = originalExpression.calleeReference
override val originalType: FirTypeRef get() = originalExpression.typeRef
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
originalExpression = originalExpression.transformSingle(transformer, data)
return this
}
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
originalExpression.accept(visitor, data)
}
override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
throw IllegalStateException()
}
override fun <D> transformExplicitReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
throw IllegalStateException()
}
override fun <D> transformDispatchReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
throw IllegalStateException()
}
override fun <D> transformExtensionReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
throw IllegalStateException()
}
override fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
throw IllegalStateException()
}
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
throw IllegalStateException()
}
override fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>) {
throw IllegalStateException()
}
override fun replaceCalleeReference(newCalleeReference: FirReference) {
throw IllegalStateException()
}
override fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?) {
throw IllegalStateException()
}
override fun replaceTypeRef(newTypeRef: FirTypeRef) {}
@FirImplementationDetail
override fun replaceSource(newSource: FirSourceElement?) {
}
}

View File

@@ -108,6 +108,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
val callableReferenceAccess = element("CallableReferenceAccess", Expression, qualifiedAccessExpression)
val thisReceiverExpression = element("ThisReceiverExpression", Expression, qualifiedAccessExpression)
val expressionWithSmartcast = element("ExpressionWithSmartcast", Expression, qualifiedAccessExpression)
val expressionWithSmartcastToNull = element("ExpressionWithSmartcastToNull", Expression, expressionWithSmartcast)
val safeCallExpression = element("SafeCallExpression", Expression, expression)
val checkedSafeCallSubject = element("CheckedSafeCallSubject", Expression, expression)
val getClassCall = element("GetClassCall", Expression, expression, call)

View File

@@ -156,6 +156,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(qualifiedAccessExpression)
noImpl(expressionWithSmartcast)
noImpl(expressionWithSmartcastToNull)
impl(getClassCall) {
default("argument") {

View File

@@ -459,6 +459,12 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+field("originalType", typeRef)
}
expressionWithSmartcastToNull.configure {
+field("originalExpression", qualifiedAccessExpression)
+field("typesFromSmartCast", "Collection<ConeKotlinType>", null, customType = coneKotlinTypeType)
+field("originalType", typeRef)
}
safeCallExpression.configure {
+field("receiver", expression).withTransform()
// Special node that might be used as a reference to receiver of a safe call after null check

View File

@@ -98,7 +98,7 @@ object JvmFileClassUtil {
it.calleeExpression?.constructorReferenceExpression?.getReferencedName() == shortName
}
private fun getLiteralStringFromAnnotation(annotation: KtAnnotationEntry): String? {
fun getLiteralStringFromAnnotation(annotation: KtAnnotationEntry): String? {
val argumentExpression = annotation.valueArguments.firstOrNull()?.getArgumentExpression() ?: return null
val stringTemplate = argumentExpression as? KtStringTemplateExpression ?: return null
val singleEntry = stringTemplate.entries.singleOrNull() as? KtLiteralStringTemplateEntry ?: return null

View File

@@ -79,8 +79,9 @@ class VirtualFileKotlinClass private constructor(
}
private fun logFileReadingErrorMessage(e: Throwable, file: VirtualFile): Throwable {
LOG.warn(renderFileReadingErrorMessage(file), e)
return e
val errorMessage = renderFileReadingErrorMessage(file)
LOG.warn(errorMessage, e)
return IllegalStateException(errorMessage, e)
}
private fun renderFileReadingErrorMessage(file: VirtualFile): String =

View File

@@ -261,8 +261,8 @@ class ResolvedAtomCompleter(
}
}
val substitutedValueParameterTypes = descriptor.valueParameters.mapIndexed { i, valueParameter ->
valueParameterTypes[i].substituteAndApproximate(substitutor).also {
val substitutedValueParameterTypes = descriptor.valueParameters.mapIndexedNotNull { i, valueParameter ->
valueParameterTypes.getOrNull(i)?.substituteAndApproximate(substitutor)?.also {
if (valueParameter is ValueParameterDescriptorImpl && valueParameter.type.shouldBeUpdated()) {
valueParameter.setOutType(it.approximatedType)
}

View File

@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.resolve.diagnostics
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.util.CompositeModificationTracker
import com.intellij.psi.PsiElement
import com.intellij.psi.util.CachedValueProvider
@@ -48,8 +49,10 @@ class MutableDiagnosticsWithSuppression(
override fun noSuppression() = readonlyView().noSuppression()
override fun setCallback(callback: DiagnosticSink.DiagnosticsCallback) {
// TODO: [VD] temporary dirty patch, proper investigation is required
// assert(diagnosticsCallback == null) { "diagnostic callback has been already registered" }
diagnosticsCallback?.let {
Logger.getInstance(MutableDiagnosticsWithSuppression::class.java).error("diagnostic callback has been already registered")
return
}
diagnosticsCallback = callback
delegateDiagnostics.setCallback(callback)
}

View File

@@ -35,7 +35,8 @@ class InitializersLowering(context: CommonBackendContext) : InitializersLowering
val irClass = container.constructedClass
val instanceInitializerStatements = extractInitializers(irClass) {
(it is IrField && !it.isStatic) || (it is IrAnonymousInitializer && !it.isStatic)
(it is IrField && !it.isStatic && (container.isPrimary || !it.primaryConstructorParameter)) ||
(it is IrAnonymousInitializer && !it.isStatic)
}
val block = IrBlockImpl(irClass.startOffset, irClass.endOffset, context.irBuiltIns.unitType, null, instanceInitializerStatements)
// Check that the initializers contain no local classes. Deep-copying them is a disaster for code size, and liable to break randomly.
@@ -54,6 +55,9 @@ class InitializersLowering(context: CommonBackendContext) : InitializersLowering
}
}
private val IrField.primaryConstructorParameter: Boolean
get() = (initializer?.expression as? IrGetValue)?.origin == IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER
abstract class InitializersLoweringBase(open val context: CommonBackendContext) {
protected fun extractInitializers(irClass: IrClass, filter: (IrDeclaration) -> Boolean) =
// TODO What about fields that were added by lowerings? e.g. captured outer class or locals?

View File

@@ -53,6 +53,8 @@ fun IrType.isTypeParameter() = classifierOrNull is IrTypeParameterSymbol
fun IrType.isInterface() = classOrNull?.owner?.kind == ClassKind.INTERFACE
fun IrType.isAnnotation() = classOrNull?.owner?.kind == ClassKind.ANNOTATION_CLASS
fun IrType.isFunctionOrKFunction() = isFunction() || isKFunction()
fun IrType.isSuspendFunctionOrKFunction() = isSuspendFunction() || isKSuspendFunction()
@@ -141,8 +143,24 @@ private fun collectAllSupertypes(irType: IrSimpleType, result: MutableSet<IrSimp
// for the class C, this function constructs:
// { B<List<Z>>, A<List<List<Z>>, Any }
// where Z is a type parameter of class C.
fun getAllSubstitutedSupertypes(irClass: IrClass): MutableSet<IrSimpleType> {
fun getAllSubstitutedSupertypes(irClass: IrClass): Set<IrSimpleType> {
val result = HashSet<IrSimpleType>()
collectAllSupertypes(irClass.defaultType, result)
return result
}
private fun collectAllSuperclasses(irClass: IrClass, set: MutableSet<IrClass>) {
for (superType in irClass.superTypes) {
val classifier = superType.classifierOrNull as? IrClassSymbol ?: continue
val superClass = classifier.owner
if (set.add(superClass)) {
collectAllSuperclasses(superClass, set)
}
}
}
fun IrClass.getAllSuperclasses(): Set<IrClass> {
val result = HashSet<IrClass>()
collectAllSuperclasses(this, result)
return result
}

View File

@@ -171,8 +171,7 @@ open class JvmIrCodegenFactory(
val result = LinkedHashSet<ModuleDescriptor>()
fun collectImpl(descriptor: ModuleDescriptor) {
val dependencies = descriptor.allDependencyModules
dependencies.forEach { if (it !in result) collectImpl(it) }
result += dependencies
dependencies.forEach { if (result.add(it)) collectImpl(it) }
}
collectImpl(this)
return result.toList()

View File

@@ -196,6 +196,7 @@ class JvmCachedDeclarations(
isSuspend = target.isSuspend
}.apply proxy@{
parent = this@makeProxy
copyAttributes(target)
copyTypeParametersFrom(target)
copyAnnotationsFrom(target)
if (!isStatic) {

View File

@@ -43,9 +43,7 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.org.objectweb.asm.AnnotationVisitor
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.TypePath
import org.jetbrains.org.objectweb.asm.*
import java.lang.annotation.RetentionPolicy
abstract class AnnotationCodegen(
@@ -107,10 +105,10 @@ abstract class AnnotationCodegen(
generateTypeAnnotations(annotated, typeForTypeAnnotations)
}
abstract fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor
abstract fun visitAnnotation(descr: String, visible: Boolean): AnnotationVisitor
open fun visitTypeAnnotation(
descr: String?,
descr: String,
path: TypePath?,
visible: Boolean,
): AnnotationVisitor {
@@ -287,6 +285,64 @@ abstract class AnnotationCodegen(
}
companion object {
fun genAnnotationsOnTypeParametersAndBounds(
context: JvmBackendContext,
typeParameterContainer: IrTypeParametersContainer,
classCodegen: ClassCodegen,
referenceType: Int,
boundType: Int,
visitor: (typeRef: Int, typePath: TypePath?, descriptor: String, visible: Boolean) -> AnnotationVisitor
) {
if (context.state.target != JVM_1_6) {
typeParameterContainer.typeParameters.forEachIndexed { index, typeParameter ->
object : AnnotationCodegen(classCodegen, context, true) {
override fun visitAnnotation(descr: String, visible: Boolean): AnnotationVisitor {
return visitor(
TypeReference.newTypeParameterReference(referenceType, index).value,
null,
descr,
visible
)
}
override fun visitTypeAnnotation(descr: String, path: TypePath?, visible: Boolean): AnnotationVisitor {
throw RuntimeException(
"Error during generation: type annotation shouldn't be presented on type parameter: " +
"${ir2string(typeParameter)} in ${ir2string(typeParameterContainer)}"
)
}
}.genAnnotations(typeParameter, null, null)
if (context.state.configuration.getBoolean(JVMConfigurationKeys.EMIT_JVM_TYPE_ANNOTATIONS)) {
var superInterfaceIndex = 1
typeParameter.superTypes.forEach { superType ->
val isClassOrTypeParameter = !superType.isInterface() && !superType.isAnnotation()
val superIndex = if (isClassOrTypeParameter) 0 else superInterfaceIndex++
object : AnnotationCodegen(classCodegen, context, true) {
override fun visitAnnotation(descr: String, visible: Boolean): AnnotationVisitor {
throw RuntimeException(
"Error during generation: only type annotations should be presented on type parameters bounds: " +
"${ir2string(typeParameter)} in ${ir2string(typeParameter)}"
)
}
override fun visitTypeAnnotation(descr: String, path: TypePath?, visible: Boolean): AnnotationVisitor {
return visitor(
TypeReference.newTypeParameterBoundReference(boundType, index, superIndex).value,
path,
descr,
visible
)
}
}.generateTypeAnnotations(typeParameterContainer, superType)
}
}
}
}
}
private fun isInvisibleForNullabilityAnalysis(declaration: IrDeclaration): Boolean =
when {
declaration.origin.isSynthetic ->
@@ -336,7 +392,7 @@ abstract class AnnotationCodegen(
val IrConstructorCall.annotationClass get() = symbol.owner.parentAsClass
}
private fun generateTypeAnnotations(
internal fun generateTypeAnnotations(
annotated: IrAnnotationContainer,
type: IrType?
) {

View File

@@ -153,10 +153,21 @@ class ClassCodegen private constructor(
}
object : AnnotationCodegen(this@ClassCodegen, context) {
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
override fun visitAnnotation(descr: String, visible: Boolean): AnnotationVisitor {
return visitor.visitor.visitAnnotation(descr, visible)
}
}.genAnnotations(irClass, null, null)
AnnotationCodegen.genAnnotationsOnTypeParametersAndBounds(
context,
irClass,
this,
TypeReference.CLASS_TYPE_PARAMETER,
TypeReference.CLASS_TYPE_PARAMETER_BOUND
) { typeRef: Int, typePath: TypePath?, descriptor: String, visible: Boolean ->
visitor.visitor.visitTypeAnnotation(typeRef, typePath, descriptor, visible)
}
generateKotlinMetadataAnnotation()
generateInnerAndOuterClasses()
@@ -306,11 +317,11 @@ class ClassCodegen private constructor(
flags and (Opcodes.ACC_SYNTHETIC or Opcodes.ACC_ENUM) != 0 ||
field.origin == JvmLoweredDeclarationOrigin.FIELD_FOR_STATIC_CALLABLE_REFERENCE_INSTANCE
object : AnnotationCodegen(this@ClassCodegen, context, skipNullabilityAnnotations) {
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
override fun visitAnnotation(descr: String, visible: Boolean): AnnotationVisitor {
return fv.visitAnnotation(descr, visible)
}
override fun visitTypeAnnotation(descr: String?, path: TypePath?, visible: Boolean): AnnotationVisitor {
override fun visitTypeAnnotation(descr: String, path: TypePath?, visible: Boolean): AnnotationVisitor {
return fv.visitTypeAnnotation(TypeReference.newTypeReference(TypeReference.FIELD).value, path, descr, visible)
}
}.genAnnotations(field, fieldType, field.type)

View File

@@ -144,6 +144,7 @@ private fun IrFunction.isStaticInlineClassReplacementDelegatingCall(): Boolean =
private val BRIDGE_ORIGINS = setOf(
IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER,
JvmLoweredDeclarationOrigin.JVM_STATIC_WRAPPER,
JvmLoweredDeclarationOrigin.JVM_OVERLOADS_WRAPPER,
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR,

View File

@@ -16,8 +16,6 @@ import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
import org.jetbrains.kotlin.backend.jvm.ir.isInlineClassType
import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry
import org.jetbrains.kotlin.backend.jvm.lower.constantValue
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.isInlineCallableReference
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.isMappedToPrimitive
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.requiresMangling
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
import org.jetbrains.kotlin.backend.jvm.lower.isMultifileBridge
@@ -648,27 +646,16 @@ class ExpressionCodegen(
val type = frameMap.typeOf(expression.symbol)
mv.load(findLocalIndex(expression.symbol), type)
unboxResultIfNeeded(expression)
unboxInlineClassArgumentOfInlineCallableReference(expression)
return MaterialValue(this, type, expression.type)
}
// JVM_IR generates inline callable differently from the old backend:
// it generates them as normal functions and not objects.
// Thus, we need to unbox inline class argument with reference underlying type.
private fun unboxInlineClassArgumentOfInlineCallableReference(arg: IrGetValue) {
if (!arg.type.isInlineClassType()) return
if (arg.type.isMappedToPrimitive) return
if (!irFunction.isInlineCallableReference) return
if (irFunction.extensionReceiverParameter?.symbol == arg.symbol) return
if (arg.type.isNullable() && arg.type.makeNotNull().unboxInlineClass().isNullable()) return
StackValue.unboxInlineClass(OBJECT_TYPE, arg.type.erasedUpperBound.defaultType, mv, typeMapper)
}
// We do not mangle functions if Result is the only parameter of the function,
// thus, if the function overrides generic parameter, its argument is boxed and there is no
// bridge to unbox it. Instead, we unbox it in the non-mangled function manually.
private fun unboxResultIfNeeded(arg: IrGetValue) {
if (arg.type.erasedUpperBound.fqNameWhenAvailable != StandardNames.RESULT_FQ_NAME) return
// Unlike inline callable reference arguments, nullable Result arguments are unboxed during coercion to not-null Result
if (arg.type.isNullable()) return
// Do not unbox arguments of lambda, but unbox arguments of callable references
if (irFunction.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA) return
if (!onlyResultInlineClassParameters()) return

View File

@@ -79,16 +79,27 @@ class FunctionCodegen(
if (irFunction.origin !in methodOriginsWithoutAnnotations) {
val skipNullabilityAnnotations = flags and Opcodes.ACC_PRIVATE != 0 || flags and Opcodes.ACC_SYNTHETIC != 0
object : AnnotationCodegen(classCodegen, context, skipNullabilityAnnotations) {
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
override fun visitAnnotation(descr: String, visible: Boolean): AnnotationVisitor {
return methodVisitor.visitAnnotation(descr, visible)
}
override fun visitTypeAnnotation(descr: String?, path: TypePath?, visible: Boolean): AnnotationVisitor {
override fun visitTypeAnnotation(descr: String, path: TypePath?, visible: Boolean): AnnotationVisitor {
return methodVisitor.visitTypeAnnotation(
TypeReference.newTypeReference(TypeReference.METHOD_RETURN).value, path, descr, visible
)
}
}.genAnnotations(irFunction, signature.asmMethod.returnType, irFunction.returnType)
AnnotationCodegen.genAnnotationsOnTypeParametersAndBounds(
context,
irFunction,
classCodegen,
TypeReference.METHOD_TYPE_PARAMETER,
TypeReference.METHOD_TYPE_PARAMETER_BOUND
) { typeRef: Int, typePath: TypePath?, descriptor: String, visible: Boolean ->
methodVisitor.visitTypeAnnotation(typeRef, typePath, descriptor, visible)
}
if (shouldGenerateAnnotationsOnValueParameters()) {
generateParameterAnnotations(irFunction, methodVisitor, signature, classCodegen, context, skipNullabilityAnnotations)
}
@@ -218,7 +229,7 @@ class FunctionCodegen(
private fun generateAnnotationDefaultValueIfNeeded(methodVisitor: MethodVisitor) {
getAnnotationDefaultValueExpression()?.let { defaultValueExpression ->
val annotationCodegen = object : AnnotationCodegen(classCodegen, context) {
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
override fun visitAnnotation(descr: String, visible: Boolean): AnnotationVisitor {
return methodVisitor.visitAnnotationDefault()
}
}
@@ -279,7 +290,7 @@ class FunctionCodegen(
if (annotated != null && !kind.isSkippedInGenericSignature && !annotated.isSyntheticMarkerParameter()) {
object : AnnotationCodegen(innerClassConsumer, context, skipNullabilityAnnotations) {
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
override fun visitAnnotation(descr: String, visible: Boolean): AnnotationVisitor {
return mv.visitParameterAnnotation(
i - syntheticParameterCount,
descr,
@@ -287,7 +298,7 @@ class FunctionCodegen(
)
}
override fun visitTypeAnnotation(descr: String?, path: TypePath?, visible: Boolean): AnnotationVisitor {
override fun visitTypeAnnotation(descr: String, path: TypePath?, visible: Boolean): AnnotationVisitor {
return mv.visitTypeAnnotation(
TypeReference.newFormalParameterReference(i - syntheticParameterCount).value,
path, descr, visible

View File

@@ -20,11 +20,11 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.Method
@@ -201,27 +201,33 @@ class IrExpressionLambdaImpl(
private val loweredMethod = codegen.methodSignatureMapper.mapAsmMethod(function)
val capturedParamsInDesc: List<Type> = if (isBoundCallableReference) {
loweredMethod.argumentTypes.take(1)
} else loweredMethod.argumentTypes.drop(if (isExtensionLambda) 1 else 0).take(capturedVars.size)
private val captureParameterIndices: Pair<Int, Int>
get() = when {
isBoundCallableReference -> 0 to 1 // (bound receiver, real parameters...)
isExtensionLambda -> 1 to capturedVars.size + 1 // (unbound receiver, captures..., real parameters...)
else -> 0 to capturedVars.size // (captures..., real parameters...)
}
val capturedParamsInDesc: List<Type> =
captureParameterIndices.let { (from, to) -> loweredMethod.argumentTypes.take(to).drop(from) }
override val invokeMethod: Method = loweredMethod.let {
Method(
it.name,
it.returnType,
(if (isBoundCallableReference) it.argumentTypes.drop(1)
else (if (isExtensionLambda) it.argumentTypes.take(1) else emptyList()) +
it.argumentTypes.drop((if (isExtensionLambda) 1 else 0) + capturedVars.size)).toTypedArray()
)
val (startCapture, endCapture) = captureParameterIndices
Method(it.name, it.returnType, (it.argumentTypes.take(startCapture) + it.argumentTypes.drop(endCapture)).toTypedArray())
}
// Need the descriptor without captured parameters here.
override val invokeMethodDescriptor: FunctionDescriptor = function.originalFunction.toIrBasedDescriptor()
override val invokeMethodParameters: List<KotlinType?>
get() {
val allParameters = function.explicitParameters.map { it.type.toIrBasedKotlinType() }
val (startCapture, endCapture) = captureParameterIndices
return allParameters.take(startCapture) + allParameters.drop(endCapture)
}
override val invokeMethodReturnType: KotlinType
get() = function.returnType.toIrBasedKotlinType()
override val hasDispatchReceiver: Boolean = false
override fun getInlineSuspendLambdaViewDescriptor(): FunctionDescriptor = function.toIrBasedDescriptor()
override fun isCapturedSuspend(desc: CapturedParamDesc): Boolean =
capturedParameters[desc]?.let { it.isInlineParameter() && it.type.isSuspendFunctionTypeOrSubtype() } == true
}
@@ -229,23 +235,20 @@ class IrExpressionLambdaImpl(
class IrDefaultLambda(
lambdaClassType: Type,
capturedArgs: Array<Type>,
private val irValueParameter: IrValueParameter,
irValueParameter: IrValueParameter,
offset: Int,
needReification: Boolean
) : DefaultLambda(
lambdaClassType, capturedArgs, irValueParameter.toIrBasedDescriptor() as ValueParameterDescriptor, offset, needReification
) {
private val invoke =
(irValueParameter.type.classifierOrFail.owner as IrClass).functions.single { it.name == OperatorNameConventions.INVOKE }
override fun mapAsmSignature(sourceCompiler: SourceCompilerForInline): Method {
val invoke =
irValueParameter.type.classOrNull!!.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "invoke" }
return (sourceCompiler as IrSourceCompilerForInline).codegen.context.methodSignatureMapper.mapSignatureSkipGeneric(invoke).asmMethod
}
override fun mapAsmSignature(sourceCompiler: SourceCompilerForInline, descriptor: FunctionDescriptor): Method =
(sourceCompiler as IrSourceCompilerForInline).codegen.context.methodSignatureMapper.mapSignatureSkipGeneric(invoke).asmMethod
override fun findInvokeMethodDescriptor(): FunctionDescriptor =
(irValueParameter.type.classifierOrFail.owner as IrClass).functions.single {
it.name == OperatorNameConventions.INVOKE
}.toIrBasedDescriptor()
override fun findInvokeMethodDescriptor(isPropertyReference: Boolean): FunctionDescriptor =
invoke.toIrBasedDescriptor()
}
fun IrExpression.isInlineIrExpression() =

View File

@@ -13,8 +13,6 @@ import org.jetbrains.kotlin.backend.common.lower.parentsWithSelf
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.ir.*
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.isInlineCallableReference
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.isMappedToPrimitive
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
import org.jetbrains.kotlin.backend.jvm.lower.suspendFunctionOriginal
import org.jetbrains.kotlin.builtins.StandardNames
@@ -62,7 +60,7 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
fun mapFieldSignature(field: IrField): String? {
val sw = BothSignatureWriter(BothSignatureWriter.Mode.TYPE)
if (field.correspondingPropertySymbol?.owner?.isVar == true) {
writeParameterType(sw, field.type, field, false)
writeParameterType(sw, field.type, field)
} else {
mapReturnType(field, field.type, sw)
}
@@ -221,13 +219,6 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_INLINE_CLASS_MEMBER &&
function.name.asString() == "box-impl"
private fun forceBoxedInlineClassParametersForInliner(function: IrDeclaration, type: IrType, isBoundReceiver: Boolean): Boolean {
if (isBoundReceiver) return false
if (function !is IrSimpleFunction) return false
if (!function.isInlineCallableReference) return false
return type.isInlineClassType() && !type.isMappedToPrimitive
}
fun mapSignatureSkipGeneric(function: IrFunction): JvmMethodSignature =
mapSignature(function, true)
@@ -252,7 +243,7 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
val receiverParameter = function.extensionReceiverParameter
if (receiverParameter != null) {
writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.type, function, true)
writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.type, function)
}
for (parameter in function.valueParameters) {
@@ -265,7 +256,7 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
if (shouldBoxSingleValueParameterForSpecialCaseOfRemove(function))
parameter.type.makeNullable()
else parameter.type
writeParameter(sw, kind, type, function, parameter.symbol == function.extensionReceiverParameter?.symbol)
writeParameter(sw, kind, type, function)
}
sw.writeReturnType()
@@ -331,19 +322,16 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
sw: JvmSignatureWriter,
kind: JvmMethodParameterKind,
type: IrType,
function: IrFunction,
isReceiver: Boolean
function: IrFunction
) {
sw.writeParameterType(kind)
writeParameterType(sw, type, function, isReceiver)
writeParameterType(sw, type, function)
sw.writeParameterTypeEnd()
}
private fun writeParameterType(sw: JvmSignatureWriter, type: IrType, declaration: IrDeclaration, isReceiver: Boolean) {
private fun writeParameterType(sw: JvmSignatureWriter, type: IrType, declaration: IrDeclaration) {
if (sw.skipGenericSignature()) {
if (type.isInlineClassType() &&
(declaration.isFromJava() || forceBoxedInlineClassParametersForInliner(declaration, type, isReceiver))
) {
if (type.isInlineClassType() && declaration.isFromJava()) {
typeMapper.mapType(type, TypeMappingMode.GENERIC_ARGUMENT, sw)
} else {
typeMapper.mapType(type, TypeMappingMode.DEFAULT, sw)

View File

@@ -8,12 +8,14 @@ package org.jetbrains.kotlin.backend.jvm.codegen
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.ir.eraseTypeParameters
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.*
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.inline.v
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.isTypeParameter
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
@@ -51,7 +53,17 @@ abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type, val
}
!isFromTypeUnboxed && isToTypeUnboxed -> {
StackValue.unboxInlineClass(type, erasedTargetType, mv, typeMapper)
val irClass = codegen.irFunction.parentAsClass
if (irClass.isInline && irClass.symbol == irType.classifierOrNull && !irType.isNullable()) {
// Use getfield instead of unbox-impl inside inline classes
codegen.v.getfield(
typeMapper.classInternalName(irClass),
irClass.inlineClassFieldName.asString(),
typeMapper.mapType(irType).descriptor
)
} else {
StackValue.unboxInlineClass(type, erasedTargetType, mv, typeMapper)
}
return
}
}

View File

@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.addIfNotNull
@@ -59,6 +60,11 @@ internal class LambdaMetafactoryArgumentsBuilder(
if (!reference.origin.isLambda && !samClass.isFromJava())
return null
// Don't use JDK LambdaMetafactory for serializable lambdas
// TODO implement support for serializable lambdas with LambdaMetafactory (requires additional code for deserialization)
if (samClass.isInheritedFromSerializable())
return null
val samMethod = samClass.getSingleAbstractMethod()
?: throw AssertionError("SAM class has no single abstract method: ${samClass.render()}")
@@ -122,6 +128,12 @@ internal class LambdaMetafactoryArgumentsBuilder(
return getLambdaMetafactoryArgsOrNullInner(reference, samMethod, samType, implFun)
}
private val javaIoSerializableFqn =
FqName("java.io").child(Name.identifier("Serializable"))
private fun IrClass.isInheritedFromSerializable(): Boolean =
getAllSuperclasses().any { it.fqNameWhenAvailable == javaIoSerializableFqn }
private fun IrClass.requiresDelegationToDefaultImpls(): Boolean {
for (irMemberFun in functions) {
if (irMemberFun.modality == Modality.ABSTRACT)

View File

@@ -167,7 +167,13 @@ internal class SamDelegatingLambdaBuilder(private val jvmContext: JvmBackendCont
.irBlockBody {
+irReturn(
irCall(invokeFunction).also { invokeCall ->
invokeCall.dispatchReceiver = irGet(tmp)
// We need to cast receiver to the function type because it might have an imaginary type like KFunction2 which
// is mapped to KFunction in the codegen by default, which has no 'invoke'. Looks like correct type arguments
// are not needed here, so we use "raw" type for simplicity. If that stops working, we'll need to compute the
// correct substitution of invocableFunctionClass by visiting tmp.type's hierarchy.
val rawFunctionType = invocableFunctionClass.typeWith()
invokeCall.dispatchReceiver = irImplicitCast(irGet(tmp), rawFunctionType)
var parameterIndex = 0
invokeFunction.extensionReceiverParameter?.let {
invokeCall.extensionReceiver = irGet(lambda.valueParameters[parameterIndex++])

View File

@@ -174,11 +174,3 @@ val IrFunction.isInlineClassFieldGetter: Boolean
val IrFunction.isPrimaryInlineClassConstructor: Boolean
get() = this is IrConstructor && isPrimary && constructedClass.isInline
val IrFunction.isInlineCallableReference: Boolean
get() = origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA && name.asString().contains("\$$STUB_FOR_INLINING")
val IrType.isMappedToPrimitive: Boolean
get() = isInlineClassType() &&
!(isNullable() && makeNotNull().unboxInlineClass().isNullable()) &&
makeNotNull().unboxInlineClass().isPrimitiveType()

View File

@@ -105,7 +105,7 @@ import static org.jetbrains.kotlin.lexer.KtTokens.*;
IElementType tt = tt();
if (recoverySet == null ||
recoverySet.contains(tt) ||
tt == LBRACE || tt == RBRACE || tt == LONG_TEMPLATE_ENTRY_END ||
tt == LBRACE || tt == RBRACE ||
(recoverySet.contains(EOL_OR_SEMICOLON) && (eof() || tt == SEMICOLON || myBuilder.newlineBeforeCurrentToken()))) {
error(message);
}

View File

@@ -682,7 +682,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
else if (!parseLiteralConstant()) {
ok = false;
// TODO: better recovery if FIRST(element) did not match
errorWithRecovery("Expecting an element", EXPRESSION_FOLLOW);
errorWithRecovery("Expecting an element", TokenSet.orSet(EXPRESSION_FOLLOW, TokenSet.create(LONG_TEMPLATE_ENTRY_END)));
}
return ok;

View File

@@ -17,6 +17,8 @@
package org.jetbrains.kotlin.psi;
import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.navigation.ItemPresentationProviders;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -152,4 +154,9 @@ public class KtAnnotationEntry extends KtElementImplStub<KotlinAnnotationEntrySt
}
return null;
}
@Override
public ItemPresentation getPresentation() {
return ItemPresentationProviders.getItemPresentation(this);
}
}

View File

@@ -10,5 +10,6 @@ where possible options include:
-nowarn Generate no warnings
-verbose Enable verbose logging output
-version Display compiler version
-J<option> Pass an option directly to JVM
@<argfile> Read compiler arguments and file paths from the given file
OK

View File

@@ -32,6 +32,7 @@ where possible options include:
-nowarn Generate no warnings
-verbose Enable verbose logging output
-version Display compiler version
-J<option> Pass an option directly to JVM
@<argfile> Read compiler arguments and file paths from the given file
For details, see https://kotl.in/cli

View File

@@ -1,7 +1,7 @@
warning: ATTENTION!
This build uses in-dev FIR:
-Xuse-fir
compiler/testData/cli/jvm/firError.kt:5:13: error: x must be initialized before access
compiler/testData/cli/jvm/firError.kt:5:13: error: variable 'x' must be initialized
println(x)
^
compiler/testData/cli/jvm/firError.kt:10:16: error: public subclass exposes its private-in-file supertype 'Private'

View File

@@ -30,6 +30,7 @@ where possible options include:
-nowarn Generate no warnings
-verbose Enable verbose logging output
-version Display compiler version
-J<option> Pass an option directly to JVM
@<argfile> Read compiler arguments and file paths from the given file
For details, see https://kotl.in/cli

View File

@@ -0,0 +1,79 @@
// IGNORE_BACKEND: JVM
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
// RENDER_ANNOTATIONS
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
package foo
@Target(AnnotationTarget.TYPE)
annotation class TypeAnn(val name: String)
@Target( AnnotationTarget.TYPE_PARAMETER)
annotation class TypeParameterAnn(val name: String)
@Target(AnnotationTarget.TYPE_PARAMETER)
@Retention(AnnotationRetention.BINARY)
annotation class TypeParameterAnnBinary
@Target(AnnotationTarget.TYPE_PARAMETER)
@Retention(AnnotationRetention.SOURCE)
annotation class TypeParameterAnnSource
interface SimpleInterface
interface SimpleInterface2
open class SimpleClass
interface GenericInterface<Z>
open class GenericClass<Z>
@Suppress("UNSUPPORTED")
class Simple<@TypeParameterAnn("T") @TypeParameterAnnBinary @TypeParameterAnnSource T> {
fun test(p: T) : T {
return p
}
}
class TypeBound<Y, T: @foo.TypeAnn("Y") Y> {
fun test(p: T) : T {
return p
}
}
class InterfaceBound<T: @foo.TypeAnn("Interface") SimpleInterface> {
fun test(p: T) : T {
return p
}
}
class ClassBound<T: @foo.TypeAnn("Class") SimpleClass> {
fun test(p: T) : T {
return p
}
}
class ClassBoundGeneric<T: @foo.TypeAnn("Class") GenericClass<@foo.TypeAnn("SimpleClass") SimpleClass>> {
fun test(p: T) : T {
return p
}
}
class InterfaceBoundGeneric<T: @foo.TypeAnn("Interface") GenericInterface<@foo.TypeAnn("SimpleInterface") SimpleInterface>> {
fun test(p: T) : T {
return p
}
}
class ClassInterfaceBound<T: @foo.TypeAnn("Class") SimpleClass> where T : @foo.TypeAnn("Interface") SimpleInterface, T : @foo.TypeAnn("Interface2") SimpleInterface2 {
fun test(p: T) : T {
return p
}
}
class InterfaceClassBound<T: @foo.TypeAnn("Interface") SimpleInterface > where T : @foo.TypeAnn("Class") SimpleClass, T : @foo.TypeAnn("Interface2") SimpleInterface2 {
fun test(p: T) : T {
return p
}
}

View File

@@ -0,0 +1,133 @@
<T:Lfoo/SimpleClass;>Ljava/lang/Object;
public final class foo/ClassBound : java/lang/Object {
@Lfoo/TypeAnn;([name="Class"]) : CLASS_TYPE_PARAMETER_BOUND 0, 0, null
public void <init>()
(TT;)TT;
public final foo.SimpleClass test(foo.SimpleClass p)
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
}
<T:Lfoo/GenericClass<Lfoo/SimpleClass;>;>Ljava/lang/Object;
public final class foo/ClassBoundGeneric : java/lang/Object {
@Lfoo/TypeAnn;([name="Class"]) : CLASS_TYPE_PARAMETER_BOUND 0, 0, null
@Lfoo/TypeAnn;([name="SimpleClass"]) : CLASS_TYPE_PARAMETER_BOUND 0, 0, 0;
public void <init>()
(TT;)TT;
public final foo.GenericClass test(foo.GenericClass p)
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
}
<T:Lfoo/SimpleClass;:Lfoo/SimpleInterface;:Lfoo/SimpleInterface2;>Ljava/lang/Object;
public final class foo/ClassInterfaceBound : java/lang/Object {
@Lfoo/TypeAnn;([name="Class"]) : CLASS_TYPE_PARAMETER_BOUND 0, 0, null
@Lfoo/TypeAnn;([name="Interface"]) : CLASS_TYPE_PARAMETER_BOUND 0, 1, null
@Lfoo/TypeAnn;([name="Interface2"]) : CLASS_TYPE_PARAMETER_BOUND 0, 2, null
public void <init>()
(TT;)TT;
public final foo.SimpleClass test(foo.SimpleClass p)
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
}
<Z:Ljava/lang/Object;>Ljava/lang/Object;
public class foo/GenericClass : java/lang/Object {
public void <init>()
}
<Z:Ljava/lang/Object;>Ljava/lang/Object;
public abstract interface foo/GenericInterface : java/lang/Object {
}
<T::Lfoo/SimpleInterface;>Ljava/lang/Object;
public final class foo/InterfaceBound : java/lang/Object {
@Lfoo/TypeAnn;([name="Interface"]) : CLASS_TYPE_PARAMETER_BOUND 0, 1, null
public void <init>()
(TT;)TT;
public final foo.SimpleInterface test(foo.SimpleInterface p)
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
}
<T::Lfoo/GenericInterface<Lfoo/SimpleInterface;>;>Ljava/lang/Object;
public final class foo/InterfaceBoundGeneric : java/lang/Object {
@Lfoo/TypeAnn;([name="Interface"]) : CLASS_TYPE_PARAMETER_BOUND 0, 1, null
@Lfoo/TypeAnn;([name="SimpleInterface"]) : CLASS_TYPE_PARAMETER_BOUND 0, 1, 0;
public void <init>()
(TT;)TT;
public final foo.GenericInterface test(foo.GenericInterface p)
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
}
<T:Lfoo/SimpleClass;:Lfoo/SimpleInterface;:Lfoo/SimpleInterface2;>Ljava/lang/Object;
public final class foo/InterfaceClassBound : java/lang/Object {
@Lfoo/TypeAnn;([name="Interface"]) : CLASS_TYPE_PARAMETER_BOUND 0, 1, null
@Lfoo/TypeAnn;([name="Class"]) : CLASS_TYPE_PARAMETER_BOUND 0, 0, null
@Lfoo/TypeAnn;([name="Interface2"]) : CLASS_TYPE_PARAMETER_BOUND 0, 2, null
public void <init>()
(TT;)TT;
public final foo.SimpleClass test(foo.SimpleClass p)
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
}
<T:Ljava/lang/Object;>Ljava/lang/Object;
public final class foo/Simple : java/lang/Object {
public void <init>()
(TT;)TT;
public final java.lang.Object test(java.lang.Object p)
}
public class foo/SimpleClass : java/lang/Object {
public void <init>()
}
public abstract interface foo/SimpleInterface : java/lang/Object {
}
public abstract interface foo/SimpleInterface2 : java/lang/Object {
}
public abstract interface foo/TypeAnn : java/lang/Object, java/lang/annotation/Annotation {
public abstract java.lang.String name()
}
<Y:Ljava/lang/Object;T::TY;>Ljava/lang/Object;
public final class foo/TypeBound : java/lang/Object {
@Lfoo/TypeAnn;([name="Y"]) : CLASS_TYPE_PARAMETER_BOUND 1, 0, null
public void <init>()
(TT;)TT;
public final java.lang.Object test(java.lang.Object p)
}
public abstract interface foo/TypeParameterAnn : java/lang/Object, java/lang/annotation/Annotation {
public abstract java.lang.String name()
}
public abstract interface foo/TypeParameterAnnBinary : java/lang/Object, java/lang/annotation/Annotation {
}
public abstract interface foo/TypeParameterAnnSource : java/lang/Object, java/lang/annotation/Annotation {
}

View File

@@ -1,5 +1,5 @@
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
// TYPE_ANNOTATIONS
// RENDER_ANNOTATIONS
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
package foo

View File

@@ -14,6 +14,7 @@ public abstract interface foo/Ann4 : java/lang/Object, java/lang/annotation/Anno
}
<T:Ljava/lang/Object;>Ljava/lang/Object;
public final class foo/Bar : java/lang/Object {
public void <init>()
}
@@ -21,40 +22,55 @@ public final class foo/Bar : java/lang/Object {
public final class foo/Kotlin : java/lang/Object {
public void <init>()
(Lfoo/Bar<Ljava/lang/String;>;)V
public final void foo(foo.Bar s)
@Lfoo/Ann;([]) : METHOD_FORMAL_PARAMETER 0, null
@Lfoo/Ann2;([]) : METHOD_FORMAL_PARAMETER 0, 0;
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
()Lfoo/Bar<Ljava/lang/String;>;
public final foo.Bar foo()
@Lorg/jetbrains/annotations/Nullable;([]) // invisible
@Lfoo/Ann;([]) : METHOD_RETURN, null
@Lfoo/Ann2;([]) : METHOD_RETURN, 0;
<T:Ljava/lang/Object;>(TT;)V
public final void foo(java.lang.Object s)
@Lfoo/Ann;([]) : METHOD_FORMAL_PARAMETER 0, null
([Lfoo/Bar<Ljava/lang/String;>;)V
public final void fooArray(foo.Bar[] s)
@Lfoo/Ann;([]) : METHOD_FORMAL_PARAMETER 0, null
@Lfoo/Ann2;([]) : METHOD_FORMAL_PARAMETER 0, [
@Lfoo/Ann3;([]) : METHOD_FORMAL_PARAMETER 0, [0;
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
()[Lfoo/Bar<Ljava/lang/String;>;
public final foo.Bar[] fooArray()
@Lorg/jetbrains/annotations/Nullable;([]) // invisible
@Lfoo/Ann;([]) : METHOD_RETURN, null
@Lfoo/Ann2;([]) : METHOD_RETURN, [
@Lfoo/Ann3;([]) : METHOD_RETURN, [0;
([[Lfoo/Bar<Ljava/lang/String;>;)V
public final void fooArrayArray(foo.Bar[][] s)
@Lfoo/Ann;([]) : METHOD_FORMAL_PARAMETER 0, null
@Lfoo/Ann2;([]) : METHOD_FORMAL_PARAMETER 0, [
@Lfoo/Ann3;([]) : METHOD_FORMAL_PARAMETER 0, [[
@Lfoo/Ann4;([]) : METHOD_FORMAL_PARAMETER 0, [[0;
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
()[[Lfoo/Bar<Ljava/lang/String;>;
public final foo.Bar[][] fooArrayArray()
@Lorg/jetbrains/annotations/Nullable;([]) // invisible
@Lfoo/Ann;([]) : METHOD_RETURN, null
@Lfoo/Ann2;([]) : METHOD_RETURN, [
@Lfoo/Ann3;([]) : METHOD_RETURN, [[
@Lfoo/Ann4;([]) : METHOD_RETURN, [[0;
<T:Ljava/lang/Object;>(Lfoo/Bar<TT;>;)V
public final void fooGeneric(foo.Bar s)
@Lfoo/Ann;([]) : METHOD_FORMAL_PARAMETER 0, null
@Lfoo/Ann2;([]) : METHOD_FORMAL_PARAMETER 0, 0;
}
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
}

View File

@@ -1,5 +1,5 @@
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
// TYPE_ANNOTATIONS
// RENDER_ANNOTATIONS
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
package foo

View File

@@ -2,12 +2,15 @@ public final class foo/Kotlin$foo$1 : java/lang/Object {
void <init>()
public final foo.Kotlin foo()
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
}
public final class foo/Kotlin : java/lang/Object {
public void <init>(java.lang.String s, java.lang.String p)
@Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null
@Lfoo/TypeAnn;([name="123"]) : METHOD_FORMAL_PARAMETER 1, null
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 1
private void <init>(java.lang.String s)
@Lfoo/TypeAnn;([name="private"]) : METHOD_FORMAL_PARAMETER 0, null

View File

@@ -1,5 +1,5 @@
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
// TYPE_ANNOTATIONS
// RENDER_ANNOTATIONS
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
package foo

View File

@@ -2,9 +2,11 @@ public final class foo/Kotlin : java/lang/Object {
public void <init>()
public final java.lang.Object foo(java.lang.String s, int x)
@Lorg/jetbrains/annotations/Nullable;([]) // invisible
@Lfoo/TypeAnn;([name="return"]) : METHOD_RETURN, null
@Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null
@Lfoo/TypeAnn;([name="2"]) : METHOD_FORMAL_PARAMETER 1, null
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
public static java.lang.Object foo$default(foo.Kotlin p0, java.lang.String p1, int p2, int p3, java.lang.Object p4)
}

View File

@@ -0,0 +1,23 @@
// KOTLIN_CONFIGURATION_FLAGS: -JVM.EMIT_JVM_TYPE_ANNOTATIONS
// RENDER_ANNOTATIONS
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
package foo
@Target(AnnotationTarget.TYPE)
annotation class TypeAnn(val name: String)
@Target(AnnotationTarget.TYPE_PARAMETER)
annotation class TypeParameterAnn(val name: String)
class Kotlin {
fun foo(s: @TypeAnn("1") String) {
}
fun <T : @TypeAnn("Ant") Any> bar(p: T): T {
return p
}
}

View File

@@ -0,0 +1,19 @@
public final class foo/Kotlin : java/lang/Object {
public void <init>()
<T:Ljava/lang/Object;>(TT;)TT;
public final java.lang.Object bar(java.lang.Object p)
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
public final void foo(java.lang.String s)
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
}
public abstract interface foo/TypeAnn : java/lang/Object, java/lang/annotation/Annotation {
public abstract java.lang.String name()
}
public abstract interface foo/TypeParameterAnn : java/lang/Object, java/lang/annotation/Annotation {
public abstract java.lang.String name()
}

View File

@@ -1,6 +1,6 @@
// IGNORE_BACKEND: JVM_IR
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
// TYPE_ANNOTATIONS
// RENDER_ANNOTATIONS
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
package foo

View File

@@ -1,9 +1,11 @@
final class foo/Kotlin$A : foo/Kotlin {
()V
void <init>(java.lang.String $enum$name, int $enum$ordinal)
public final void foo()
}
Ljava/lang/Enum<Lfoo/Kotlin;>;
public class foo/Kotlin : java/lang/Enum {
private final static foo.Kotlin[] $VALUES
@@ -11,6 +13,7 @@ public class foo/Kotlin : java/lang/Enum {
static void <clinit>()
(Ljava/lang/String;)V
private void <init>(java.lang.String $enum$name, int $enum$ordinal, java.lang.String s)
@Lfoo/TypeAnn;([]) : METHOD_FORMAL_PARAMETER 0, null

View File

@@ -0,0 +1,16 @@
// IGNORE_BACKEND: JVM
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
// RENDER_ANNOTATIONS
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
package foo
@Target(AnnotationTarget.TYPE)
annotation class TypeAnn
enum class Kotlin (s: @TypeAnn String) {
A("123") {
fun foo() {}
};
}

View File

@@ -0,0 +1,31 @@
final class foo/Kotlin$A : foo/Kotlin {
()V
void <init>(java.lang.String $enum$name, int $enum$ordinal)
public final void foo()
}
Ljava/lang/Enum<Lfoo/Kotlin;>;
public class foo/Kotlin : java/lang/Enum {
private final static foo.Kotlin[] $VALUES
public final static foo.Kotlin A
private final static foo.Kotlin[] $values()
static void <clinit>()
(Ljava/lang/String;)V
private void <init>(java.lang.String $enum$name, int $enum$ordinal, java.lang.String s)
@Lfoo/TypeAnn;([]) : METHOD_FORMAL_PARAMETER 0, null
public void <init>(java.lang.String $enum$name, int $enum$ordinal, java.lang.String s, kotlin.jvm.internal.DefaultConstructorMarker $constructor_marker)
public static foo.Kotlin valueOf(java.lang.String value)
public static foo.Kotlin[] values()
}
public abstract interface foo/TypeAnn : java/lang/Object, java/lang/annotation/Annotation {
}

View File

@@ -1,5 +1,5 @@
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
// TYPE_ANNOTATIONS
// RENDER_ANNOTATIONS
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
package foo

View File

@@ -4,6 +4,8 @@ public final class foo/Kotlin : java/lang/Object {
public final void foo2(java.lang.String $this$foo2, java.lang.String s)
@Lfoo/TypeAnn;([name="ext"]) : METHOD_FORMAL_PARAMETER 0, null
@Lfoo/TypeAnn;([name="param"]) : METHOD_FORMAL_PARAMETER 1, null
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 1
}
public abstract interface foo/TypeAnn : java/lang/Object, java/lang/annotation/Annotation {

View File

@@ -0,0 +1,62 @@
// IGNORE_BACKEND: JVM
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
// RENDER_ANNOTATIONS
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
package foo
@Target(AnnotationTarget.TYPE)
annotation class TypeAnn(val name: String)
@Target(AnnotationTarget.TYPE)
annotation class ClassTypeAnn(val name: String)
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.BINARY)
annotation class TypeAnnBinary
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.SOURCE)
annotation class TypeAnnSource
@Target( AnnotationTarget.TYPE_PARAMETER)
annotation class TypeParameterAnn(val name: String)
@Target(AnnotationTarget.TYPE_PARAMETER)
@Retention(AnnotationRetention.BINARY)
annotation class TypeParameterAnnBinary
@Target(AnnotationTarget.TYPE_PARAMETER)
@Retention(AnnotationRetention.SOURCE)
annotation class TypeParameterAnnSource
interface Generic<Z>
class GenericClass<Z>
class B<Y>
class Kotlin {
fun <@TypeParameterAnn("TP1") @TypeParameterAnnBinary @TypeParameterAnnSource T, @TypeParameterAnn("TP2") @TypeParameterAnnBinary @TypeParameterAnnSource T2> typeParameter() {
}
fun <@TypeParameterAnn("TP") T> genericParameterAndReturn(s: @TypeAnn("1") @TypeAnnBinary @TypeAnnSource T): @TypeAnn("2") @TypeAnnBinary @TypeAnnSource T {
return s
}
fun <@TypeParameterAnn("Y") Y, @TypeParameterAnn("T") T: @TypeAnn("Generic") @TypeAnnBinary @TypeAnnSource Generic<@TypeAnn("Generic Argument") @TypeAnnBinary @TypeAnnSource Y>> genericInterfaceBound() {
}
fun <@TypeParameterAnn("Y") Y, @TypeParameterAnn("T") T: @TypeAnn("Generic") @TypeAnnBinary @TypeAnnSource GenericClass<@TypeAnn("Generic Argument") @TypeAnnBinary @TypeAnnSource Y>> genericClassBound() {
}
fun <@TypeParameterAnn("Y") Y, @TypeParameterAnn("T") T: @TypeAnn("Generic") Generic<@TypeAnn("Generic Argument") Y>> whereClause() where T : @ClassTypeAnn("Any") Any {
}
fun <@TypeParameterAnn("Y") Y, @TypeParameterAnn("T") T: @TypeAnn("Y as Bound") @TypeAnnBinary @TypeAnnSource Y> typeParameterTypeParameterBound() {
}
// Second annotation is missed: see KT-46483, remove this test after prohibition of such cases
fun <@TypeParameterAnn("T") T: Any> whereClauseWithAnnotation() where @TypeParameterAnn("Additional") T : Generic<String> {
}
}

View File

@@ -0,0 +1,98 @@
<Y:Ljava/lang/Object;>Ljava/lang/Object;
public final class foo/B : java/lang/Object {
public void <init>()
}
public abstract interface foo/ClassTypeAnn : java/lang/Object, java/lang/annotation/Annotation {
public abstract java.lang.String name()
}
<Z:Ljava/lang/Object;>Ljava/lang/Object;
public abstract interface foo/Generic : java/lang/Object {
}
<Z:Ljava/lang/Object;>Ljava/lang/Object;
public final class foo/GenericClass : java/lang/Object {
public void <init>()
}
public final class foo/Kotlin : java/lang/Object {
public void <init>()
<Y:Ljava/lang/Object;T:Lfoo/GenericClass<TY;>;>()V
public final void genericClassBound()
@Lfoo/TypeParameterAnn;([name="Y"]) : METHOD_TYPE_PARAMETER 0, null
@Lfoo/TypeParameterAnn;([name="T"]) : METHOD_TYPE_PARAMETER 1, null
@Lfoo/TypeAnn;([name="Generic"]) : METHOD_TYPE_PARAMETER_BOUND 1, 0, null
@Lfoo/TypeAnn;([name="Generic Argument"]) : METHOD_TYPE_PARAMETER_BOUND 1, 0, 0;
@Lfoo/TypeAnnBinary;([]) : METHOD_TYPE_PARAMETER_BOUND 1, 0, null // invisible
@Lfoo/TypeAnnBinary;([]) : METHOD_TYPE_PARAMETER_BOUND 1, 0, 0; // invisible
<Y:Ljava/lang/Object;T::Lfoo/Generic<TY;>;>()V
public final void genericInterfaceBound()
@Lfoo/TypeParameterAnn;([name="Y"]) : METHOD_TYPE_PARAMETER 0, null
@Lfoo/TypeParameterAnn;([name="T"]) : METHOD_TYPE_PARAMETER 1, null
@Lfoo/TypeAnn;([name="Generic"]) : METHOD_TYPE_PARAMETER_BOUND 1, 1, null
@Lfoo/TypeAnn;([name="Generic Argument"]) : METHOD_TYPE_PARAMETER_BOUND 1, 1, 0;
@Lfoo/TypeAnnBinary;([]) : METHOD_TYPE_PARAMETER_BOUND 1, 1, null // invisible
@Lfoo/TypeAnnBinary;([]) : METHOD_TYPE_PARAMETER_BOUND 1, 1, 0; // invisible
<T:Ljava/lang/Object;>(TT;)TT;
public final java.lang.Object genericParameterAndReturn(java.lang.Object s)
@Lfoo/TypeAnn;([name="2"]) : METHOD_RETURN, null
@Lfoo/TypeParameterAnn;([name="TP"]) : METHOD_TYPE_PARAMETER 0, null
@Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null
@Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible
@Lfoo/TypeAnnBinary;([]) : METHOD_FORMAL_PARAMETER 0, null // invisible
<T:Ljava/lang/Object;T2:Ljava/lang/Object;>()V
public final void typeParameter()
@Lfoo/TypeParameterAnn;([name="TP1"]) : METHOD_TYPE_PARAMETER 0, null
@Lfoo/TypeParameterAnn;([name="TP2"]) : METHOD_TYPE_PARAMETER 1, null
@Lfoo/TypeParameterAnnBinary;([]) : METHOD_TYPE_PARAMETER 0, null // invisible
@Lfoo/TypeParameterAnnBinary;([]) : METHOD_TYPE_PARAMETER 1, null // invisible
<Y:Ljava/lang/Object;T::TY;>()V
public final void typeParameterTypeParameterBound()
@Lfoo/TypeParameterAnn;([name="Y"]) : METHOD_TYPE_PARAMETER 0, null
@Lfoo/TypeParameterAnn;([name="T"]) : METHOD_TYPE_PARAMETER 1, null
@Lfoo/TypeAnn;([name="Y as Bound"]) : METHOD_TYPE_PARAMETER_BOUND 1, 0, null
@Lfoo/TypeAnnBinary;([]) : METHOD_TYPE_PARAMETER_BOUND 1, 0, null // invisible
<Y:Ljava/lang/Object;T:Ljava/lang/Object;:Lfoo/Generic<TY;>;>()V
public final void whereClause()
@Lfoo/TypeParameterAnn;([name="Y"]) : METHOD_TYPE_PARAMETER 0, null
@Lfoo/TypeParameterAnn;([name="T"]) : METHOD_TYPE_PARAMETER 1, null
@Lfoo/TypeAnn;([name="Generic"]) : METHOD_TYPE_PARAMETER_BOUND 1, 1, null
@Lfoo/TypeAnn;([name="Generic Argument"]) : METHOD_TYPE_PARAMETER_BOUND 1, 1, 0;
@Lfoo/ClassTypeAnn;([name="Any"]) : METHOD_TYPE_PARAMETER_BOUND 1, 0, null
<T:Ljava/lang/Object;:Lfoo/Generic<Ljava/lang/String;>;>()V
public final void whereClauseWithAnnotation()
@Lfoo/TypeParameterAnn;([name="T"]) : METHOD_TYPE_PARAMETER 0, null
}
public abstract interface foo/TypeAnn : java/lang/Object, java/lang/annotation/Annotation {
public abstract java.lang.String name()
}
public abstract interface foo/TypeAnnBinary : java/lang/Object, java/lang/annotation/Annotation {
}
public abstract interface foo/TypeAnnSource : java/lang/Object, java/lang/annotation/Annotation {
}
public abstract interface foo/TypeParameterAnn : java/lang/Object, java/lang/annotation/Annotation {
public abstract java.lang.String name()
}
public abstract interface foo/TypeParameterAnnBinary : java/lang/Object, java/lang/annotation/Annotation {
}
public abstract interface foo/TypeParameterAnnSource : java/lang/Object, java/lang/annotation/Annotation {
}

View File

@@ -1,6 +1,6 @@
// IGNORE_BACKEND: JVM_IR
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
// TYPE_ANNOTATIONS
// RENDER_ANNOTATIONS
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
package foo

View File

@@ -1,3 +1,4 @@
Lkotlin/jvm/internal/Lambda;Lkotlin/jvm/functions/Function0<Ljava/lang/String;>;
final class foo/Kotlin$foo4$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
final foo.Kotlin this$0
@@ -6,6 +7,7 @@ final class foo/Kotlin$foo4$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions
public java.lang.Object invoke()
public final java.lang.String invoke()
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
@Lfoo/TypeAnn;([name="2"]) : METHOD_RETURN, null
@Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible
}
@@ -14,14 +16,17 @@ public final class foo/Kotlin : java/lang/Object {
public void <init>()
public final java.lang.String foo2()
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
@Lfoo/TypeAnn;([name="2"]) : METHOD_RETURN, null
@Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible
public final java.lang.String foo3()
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
@Lfoo/TypeAnn;([name="2"]) : METHOD_RETURN, null
@Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible
public final java.lang.String foo4()
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
@Lfoo/TypeAnn;([name="2"]) : METHOD_RETURN, null
@Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible
}

View File

@@ -0,0 +1,29 @@
// IGNORE_BACKEND: JVM
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
// RENDER_ANNOTATIONS
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
package foo
@Target(AnnotationTarget.TYPE)
annotation class TypeAnn(val name: String)
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.BINARY)
annotation class TypeAnnBinary
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.SOURCE)
annotation class TypeAnnSource
class Kotlin {
fun foo2(): @TypeAnn("2") @TypeAnnBinary @TypeAnnSource String {
return "OK"
}
fun foo3() = foo2()
fun foo4() = { foo2() }()
}

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