Commit Graph

166 Commits

Author SHA1 Message Date
Dmitriy Novozhilov 40b8b682f9 [FIR] Don't save DFA implications for unstable local vars
^KT-57502 Fixed
2023-05-10 14:19:25 +00:00
Dmitriy Novozhilov 1936658e40 [FIR] Consider stability of receiver for DFA variables
^KT-57425 Fixed
2023-05-10 07:50:31 +00:00
Nikolay Lunyak 76df0f9ad1 [FIR] KT-48870: Allow resolution to InaccessibleImplicitReceiverValue
^KT-48870 Fixed
2023-05-08 14:25:54 +00:00
Kirill Rakhman bd9f36ad01 [FIR] Move type parameter scope above member and static scopes in tower
This fixes a false positive TYPE_PARAMETER_IS_NOT_AN_EXPRESSION when
a type parameter and some member, static or companion declaration have
the same name and referred to inside a class.

#KT-58028 Fixed
2023-04-27 13:59:13 +00:00
Anna Kozlova 4fe239375f [cls] write contracts information to cls stubs
^ KTIJ-24665
this information would be used to create resolved FirElements from stubs,
so no ProtoBuf would be kept in memory
2023-04-25 08:34:18 +00:00
Dmitriy Novozhilov f8dc8057f0 [FIR] Prohibit referencing type parameters in contracts ...
...if they are not reified or not belong to owner declaration of the contract

KT-57911
2023-04-18 13:31:28 +00:00
Dmitriy Novozhilov 5a92eb2c67 [FIR] Properly track problems in contract description during effect extraction 2023-04-18 13:31:28 +00:00
Dmitriy Novozhilov f8ef478647 [FIR] Assume smartacsts on member properties from friend modules as stable
^KT-57893 Fixed
2023-04-12 08:59:03 +00:00
Mikhail Glukhikh 7a58c2e99f DiagnosticReporterByTrackingStrategy: refactor positioning 2023-03-22 15:42:26 +00:00
aleksandrina-streltsova d89d774411 [AA] Consider context receivers in FirTowerDataElement.getAvailableScope 2023-03-20 22:04:48 +00:00
Mikhail Glukhikh b64cb67370 K2: support ForbidInferringTypeVariablesIntoEmptyIntersection on/off 2023-03-11 10:15:23 +00:00
Ivan Kochurkin 585343d646 [FIR] Remove SessionUtils because it's not used 2023-03-01 22:10:09 +00:00
Kirill Rakhman 2139914061 [FIR] Add diagnostic when annotation argument is resolved ambiguously
Annotation arguments that are resolved in COMPILER_REQUIRED_ANNOTATIONS
phase are resolved again in ANNOTATION_ARGUMENTS phase. If they resolve
to a different symbol, report an error.

KT-56177
2023-02-28 10:19:19 +00:00
Dmitriy Novozhilov 2a022ca9e0 [FIR] Properly propagate deadness from try main block throw finally block
^KT-56476 Fixed
2023-02-28 09:17:39 +00:00
Dmitriy Novozhilov e70e85d51a [FIR] Move unwrapSmartcastExpression util into :compiler:fir:tree module 2023-02-17 12:29:17 +00:00
Dmitriy Novozhilov 914acd841f [FIR] Add special kind for graph of init blocks and local functions 2023-02-17 11:26:17 +00:00
Denis.Zharkov a4c5e1bc87 K2: Unwrap fake overrides before using them as DFA identifiers
It's necessary because even for stable a.b.c.d we can't guarantee that
this reference will always point to the same symbol because
different capture type instantiations generate different scopes
with different resulting symbol instances.
2023-02-15 08:13:53 +00:00
Denis.Zharkov 9fa0f51a61 K2: Fix false-negative RETURN_TYPE_MISMATCH
^KT-53987 Fixed
^KT-55932 Fixed
2023-02-15 08:13:42 +00:00
Denis.Zharkov fe5adab652 K2: Avoid inference diagnostics when arguments are already error typed
For example, NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER

It became especially relevant after 0e84bf2053
that together with later commits bring a lot of unnecessary
NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER diagnostic
2023-02-15 08:13:41 +00:00
Jaebaek Seo a09d0aa1cf Handle SHORTEN_IF_ALEADY_IMPORTED case of KtFirReferenceShortener
For the following example, when we run the reference shortener, it
drops `a.b.c` qualifier, because it matches "FOURTH".
```
package a.b.c

fun <T, E, D> foo(a: T, b: E, c: D) = a.hashCode() + b.hashCode() + c.hashCode() // FIRST
fun <E> E.foo() = hashCode() // SECOND

object Receiver {
    fun <T, E, D> foo(a: T, b: E, c: D) = a.hashCode() + b.hashCode() + c.hashCode() // THIRD
    fun foo(a: Int, b: Boolean, c: String) = a.hashCode() + b.hashCode() + c.hashCode() // FOURTH
    fun test(): Int {
        fun foo(a: Int, b: Boolean, c: Int) = a + b.hashCode() + c // FIFTH
        return <expr>a.b.c.foo(1, false, "bar")</expr>
    }
}
```

As shown in the above example, when SHORTEN_IF_ALEADY_IMPORTED option is
given from a user, the reference shortener has to check whether it can
drop the qualifier without changing the referenced symbol and if it is
possible to do that without adding a new import directive, it deletes
the qualifier.

It needs two steps:
 1. Collect all candidate symbols matching the signature e.g., function
    arguments / type arguments
 2. Determine whether the referenced symbol has the highest reference
    priority when we drops the qualifier depending on scopes

This commit uses `AllCandidatesResolver(shorteningContext.analysisSession.useSiteSession).
getAllCandidates( .. fake FIR call/property-access ..)` for step1.
For step2, we use a heuristic based on scopes of candidates. If a
candidate symbol is under the same scope with the target expression, it
has a `FirLocalScope` which has the high priority. So when we have a
candidate under a `FirLocalScope` and the actual referenced symbol is
different from the candidate, we must avoid dropping its qualifier
because the shortening will change its semantics i.e., reference.

The order of scopes depending on their scope types is:
 1. FirLocalScope
 2. FirClassUseSiteMemberScope / FirNestedClassifierScope
 3. FirExplicitSimpleImportingScope
 4. FirPackageMemberScope
 5. others

Note that for "others" the above rule can be wrong. Please update it if
you find other scopes that have a priority higher than the specified
scopes.

One of non-trivial parts is the priority among multiple
FirClassUseSiteMemberScope and FirNestedClassifierScope. They are
basically scopes for class declarations. We decide their priorities
based on the distance of class declaration from the target expression.

Note that we take a strict approach to reject all false positive. For
example, when we are not sure, we don't shorten it to avoid changing its
semantics.

TODO: One corner case is handling receivers. We have to update
```
private fun shortenIfAlreadyImported(
    firQualifiedAccess: FirQualifiedAccess,
    calledSymbol: FirCallableSymbol<*>,
    expressionInScope: KtExpression,
): Boolean
```

The current implementation cannot handle the following example:
```
package foo
class Foo {
    fun test() {
        // It references FIRST. Removing `foo` lets it reference SECOND.
        <caret>foo.myRun {
            42
        }
    }
}
inline fun <R> myRun(block: () -> R): R = block()         // FIRST
inline fun <T, R> T.myRun(block: T.() -> R): R = block()  // SECOND
```

Tests related to TODO:
 - analysis/analysis-api/testData/components/referenceShortener/referenceShortener/receiver2.kt
 - analysis/analysis-api/testData/components/referenceShortener/referenceShortener/receiver3.kt
2023-02-08 18:39:12 +00:00
Kirill Rakhman ace47c06a5 FIR: Make LHS of FirVariableAssignment a FirExpression
This way references can even be resolved for erroneous assignments
(e.g. function call, if expression, ... on LHS)

^KT-54648 Fixed
2023-01-31 08:39:42 +00:00
Dmitriy Novozhilov 4941fcd10e [FIR] Report PRIVATE_CLASS_MEMBER_FROM_INLINE on qualifiers of companions
^KT-56172 Fixed
^KT-55179
2023-01-31 07:53:12 +00:00
Mikhail Glukhikh 8aed6d3c4c K2: add dispatchReceiverForStatics to ScopeTowerLevel to avoid receiver hacks
Related to KT-55116
2023-01-26 15:27:58 +00:00
pyos 166ddd9ea9 FIR CFA: make node unionness a runtime property
Class exit node should only unify data flow if it is an anonymous
object, in which case it only has one control flow input. Coversely,
any other class exit node has normal merge semantics for its control
flow inputs, but it won't have any data flow inputs.
2023-01-26 13:12:11 +00:00
pyos 8aa50e9446 FIR CFA: add edges from maybe-throwing statements to catch/finally 2023-01-26 09:50:24 +00:00
pyos 308e1362ab Minor: FIR DFA: fix code style 2023-01-10 15:40:53 +02:00
pyos 5d4b44500a FIR CFA: remove direction from ControlFlowGraph.traverse.
If you care about direction, then you also care about labels.

3 out of 6 places that use `traverse` are incorrect, by the way.
Node order does not correspond to scoping boundaries.
2023-01-10 15:40:53 +02:00
pyos da018e9d06 FIR CFA: align reading of labels with the way they're generated
UncaughtExceptionPath label out of a finally block matches every label
that is not handled by another edge, and a labeled edge from the middle
of a finally block aborts the jump and so should merge all available
data.
2023-01-10 15:40:52 +02:00
pyos e86b87fe0b Test: FIR CFA: fix the names of some nodes 2023-01-10 15:40:52 +02:00
pyos 5a79017879 FIR CFA: remove some redundant node stacks
Honestly the amount of mutable state in the builder makes me somewhat
uneasy.
2023-01-10 15:40:51 +02:00
pyos 60662663be FIR CFA: remove the id parameter from nodes 2023-01-10 15:40:51 +02:00
pyos 377b7bdf5e FIR CFA: remove top-level graph
It should never have contained any nodes because it was not attached
to anything.
2023-01-10 15:40:50 +02:00
pyos 0dd949bb36 FIR DFA: route data flow through anonymous objects
^KT-44515 Fixed
2023-01-10 15:40:50 +02:00
pyos c6e9afb788 FIR CFA: remove class initializer part nodes
Instead, attach subgraphs directly to the class enter node.
2023-01-10 15:40:50 +02:00
pyos b9f366af05 FIR CFA: remove infinite loops from toposort
Finally, no more tests getting stuck on `orderNodes`. Only took me what,
75 commits to fix enough things to make this actually work?
2023-01-10 15:40:50 +02:00
pyos 3887c80816 FIR CFA: ensure on API level that graphs have enter & exit
What's going on with script graphs?..
2023-01-10 15:40:49 +02:00
pyos e710edbd77 FIR CFA: use a common fake node for annotation calls and contracts
The graphs for both will be completely discarded and should never be
visited.
2023-01-10 15:40:49 +02:00
pyos 4c6eff9174 FIR CFA: compute subgraph relationships automatically
No more `addSubGraph`. Also no more `owner` in graphs.

^KT-40526 Obsolete
^KT-40582 Obsolete
2023-01-10 15:40:48 +02:00
pyos 7ff5ad1ad0 FIR CFA: remove modes
They are only used in one place that can just as well use kinds.

Especially considering that "the one place" used them incorrectly and
would not attach local functions in property accessors as subgraphs.
2023-01-10 15:40:48 +02:00
pyos 5d4fb3ead8 FIR CFA: add control flow between default parameter values
function enter -> default 1 -> default 2 -> rest of function
                   \----------^ \----------^

This probably has no effect (in non-stupid code, at least), but it makes
graph construction more architecturally correct (now value parameters'
subgraphs get attached to a node).
2023-01-10 15:40:48 +02:00
pyos 74758278d7 FIR CFA: attach method graphs to class exit node
Even for non-local classes. This ensures that the CFG edges in this case
will only go to a subgraph, not to an unrelated graph.
2023-01-10 15:40:48 +02:00
pyos e7e5569539 FIR CFA: do not remove provideDelegate subgraphs when rolling back
The receiver of the provideDelegate call is the same FirExpression as
the delegate itself, so there's only one copy of the nodes in the first
place; trying to remove subgraphs completely detaches objects inside it
from the parent graph, which is not great for checkers.

Note that currently if provideDelegate is not selected, there will be a
stray FunctionCallExit node in the control flow graph. This commit *does
not change that*. It has been there for a while. Don't @ me. I'll try to
fix that. No promises.
2023-01-10 15:40:47 +02:00
pyos fa0ea1504e FIR CFA: remove CFGNode.outgoingEdges
If it's symmetric with incomingEdges, then what's the point?..
2023-01-10 15:40:47 +02:00
pyos 7feeb7cd4e FIR CFA: remove edge kind merging
There shouldn't be any duplicate edges anymore. There probably weren't
any before, either.
2023-01-10 15:40:47 +02:00
pyos 069d99c5ea FIR CFA: rewrite handling of try-catch-finally
The result is the same, but it should now be much clearer what the
shortcomings of the current implementation are.
2023-01-10 15:40:47 +02:00
pyos faf0129a5d Test: FIR CFA: sort edges by style & target node id 2023-01-10 15:40:46 +02:00
pyos 1eccb9aea1 FIR: assume a lambda returns Unit if it ends with a non-expression
While it is theoretically useful to know that `{ while(true) {} }`
returns Nothing, CFG node deadness is not precise enough to do that: if
the entire lambda is dead, it's no longer possible to find out whether
the loop is terminating. Besides, `while (true)` and `if (true)` are
pretty much the only constructs like that anyway.

Note that this commit does not affect resolution for lambdas that end in
a Nothing-returning expression, e.g. `throw`.
2023-01-10 15:40:46 +02:00
Dmitriy Novozhilov 4bddb27ca3 [FIR] Get rid of candidateSymbol in FirNamedReference
`candidateSymbol` has any reasonable meaning only for references with
  not completed candidate, so this property is moved from FirNamedReference
  to new node FirNamedReferenceWithCandidateSymbol, which has real
  implementation only in :resolve module (`FirNamedReferenceWithCandidate`)
2022-12-20 08:12:07 +00:00
Mikhail Glukhikh 03afc1f2d8 K2: don't create so large arrays in each CFGNode 2022-12-16 12:06:19 +00:00
Mikhail Glukhikh cc53671395 K2: optimize out empty maps in CFG nodes 2022-12-15 13:20:26 +00:00