This change uncovered the following problem in pipeline: we have a contract,
that all bodies will be generated after all fake overrides will be preprocessed.
But DataClassMembersGenerator generates bodies before f/o creation,
which leads to the problem, if data class has forward reference to some
class which was not processed before (because in this case generator
of `hashCode` function will try to reference f/o, which is not created yet,
which leads to `SymbolAlreadyBound` problem)
```
data class Some(val a: A) {
generated fun hashCode(): Int {
return a.hashCode() // (1) is not generated yet
}
}
class A {
fake-override fun hashCode(): Int // (1)
}
```
This problem will be fixed in the next commit
(related test is compiler/testData/codegen/box/ir/kt52677.kt)
^KT-60924
Rename to "expect" and "actual" annotation.
This will be needed in next commit to make it clear that
only expect annotation value needs special handling.
^KTIJ-26700
In the following scenario, when we search corresponding expect member
for actual `A.B`, we can skip checking compatibility of `B` scope.
```
class A {
class B {
fun foo() {}
}
}
actual typealias AImpl = A
```
This is because:
1. Annotation checker runs no matter if found expect class is compatible
or not.
2. Class always has at most one corresponding `expect` class (unlike for
functions, which may have several overrides), so we are sure that we
found the right member.
^KT-60668
^KT-60936
Currently, there is only attribute `ExpectForActualAttributeKey`
where mapping is stored only for source declarations with `actual`
modifier. But we need mapping of all class members, including classes
which were actualized via `actual typealias` or fake override members.
This data will be needed for the annotation checker in subsequent
commits.
^KT-60668
^KT-60936
Separate callable and class checks to prepare for checking
class scopes. Extract common checks to separate methods.
Also, it is found that in IR checker annotations on type parameters also checked,
because they stored in `matchedExpectToActual`. But it is expected that
only classes and callables are checked. This started to fail because of
added input parameter type checks inside `areAnnotationsCompatible`.
That's why `expectSymbol is IrTypeParameterSymbol` early-return is added.
^KT-60668
^KT-60936
IrSetField was transformed to its value to preserve side effects
This transformation produced invalid IR in cases where
IrSetField used in Unit-returning expression context.
This commit fixes it by producing Unit-typed expression
^KT-59084 Fixed
^KT-59665 Fixed
Review: https://jetbrains.team/p/kt/reviews/11039/timeline
It's better to have this logic in common place
(AbstractExpectActualCompatibilityChecker) to avoid missing compilation
errors in the future
This commit fixes:
1. Missing compilation error for actual function with default arguments
for 'actual typealias' KT-59665
2. Missing compilation error for actual function with default arguments
for actual fake-override KT-59665
Alternative solution for KT-59665 is to create a special checker.
"incompatibility" vs "special checker":
Arguments for common incompatibility:
- What if we had a rule that expect and actual default params must
match? If so then it certainly would be an incompatibility.
- Technically, we do the matching of expect and actual params (because
we allow default params in common ancestors of expect and actual
declarations).
- It's hard to check that the actual definition doesn't use default
params because `ExpectedActualResolver.findActualForExpected` filters
out fake-overrides and doesn't return them. It's not clear logic for
me, that I'm afraid to touch.
implicitActualFakeOverride_AbstractMap.kt test breaks if you drop this
weird logic
- WEAK incompatibilities can be considered as "checkers". So it doesn't
matter how it's implemented, as a "incompatibility" or a "checker"
Arguments against common incompatibility:
- Although we match expect and actual declarations to allow default
params in common ancestors of expect and actual declarations, it's
still can be considered that we check that the actual declaration
doesn't have default params. And it doesn't feel right that we check
correctness of the actual declaration in expect-actual matcher.
- ~~It may change the rules of expect actual matching~~ (It's not true,
because ActualFunctionWithDefaultParameters is declared as WEAK
incompatibility)
Currently, property `hasSourceAnnotationsErased` returns the opposite
to what is stated in name. Invert it both in implementation and on
call site.
^KT-58551
There's also SYNTHETIC_OFFSET, which is used for example for
declarations generated by interface delegation, for which
`sourceElement` threw exception. It didn't lead to any user-visible
error AFAIK, I've encountered this problem while working on 5f2ff06296.
Do not try to find PSI element, but always use the IR element offsets
instead. This greatly simplifies test data because we don't need to have
custom PSI- and LT- based diagnostic ranges in every test, and K1/K2
behavior also is mostly the same.
The exact offset ranges are not as important for backend diagnostics, so
it's better to have K2+PSI and K2+LT behaving the same.
By ignoring type parameters. Since type parameters in annotations are a
very limited feature, their sole use is to be able to specify them as
KClass argument: annotation class Foo<T: Any>(val bar: KClass<T>).
Since we can encounter type param only as a KClass type argument (and
never as a property type), simple approach of ignoring them works fine.
In that case, since we simply copy property types to synthetic
implementation class, its properties in IR start look like this:
annotation class FooImpl(override val bar: KClass<T of Foo>). This IR
seems to be not completely correct, since FooImpl.bar type contains T of
Foo param, which is out of its scope. However, so far I didn't
encounter any problems with this during testing and after MR discussion
this approach has been considered possible.
#KT-59558 Fixed
#KT-59036 Fixed
Many errors are reported in stdlib with these annotations
(SinceKotlin, Deprecated, so on).
But having them only on expect is a valid case. E.g. SinceKotlin added
if some old platform-specific API becomes commonized.
^KT-58551
This implementation only checks annotations set on expect/actual
declarations and requires further refinement (e.g. checking of other
annotation targets, class scopes within typealiases).
^KT-58551
This will help in some lowerings which need to change the callee of a
call. Instead of creating a new call and copying everything (type
arguments, value arguments, receivers, annotations, attributes, ...),
it's easier to modify the `symbol`. In a way, this is a continuation of
22b4b29292.