Terminating a CFG node because the result is Nothing should be reserved
for explicit Nothing type definitions, and not apply when smartcasting.
This allows boolean expressions to propagate implications correctly even
when the RHS is impossible or will never be executed.
^KT-47931 Fixed
The change is needed for the parallel resolution (^KT-55750), so we can resolve the declaration
under a lock that is specific to this declaration.
Previously, if LL FIR was resolving some FirClass, LL FIR resolved all its children too, and it had no control over what parts of the FIR tree were modified.
The same applied to the designation path, sometimes the classes on the designation path
might be unexpectedly (and without lock) modified.
This commit introduces LLFirResolveTarget, which specifies which exact declarations should be resolved during the lazy resolution of the declaration.
All elements outside the declarations specified for resolve in LLFirResolveTarget, should not be modified.
The logic of lazy transformers is the following:
- Go to target declaration collecting all scopes from the file and containing classes
- Resolve only declarations that are specified by the LLFirResolveTarget, performing the resolve under a separate lock for each declaration
^KT-56543
^KT-57619 Fixed
The compiler should only report diagnostics for
comparisons over builtins and identity-less types,
other incompatibilities should be reported
via inspections.
It's ok that in `equalityChecksOnIntegerTypes`
instead of `EQUALITY_NOT_APPLICABLE_WARNING` we get
`EQUALITY_NOT_APPLICABLE`, because
`ProperEqualityChecksInBuilderInferenceCalls`
is already active by default.
This change also replaces the notion of a representative superclass
with the least upper bound.
This makes complex types like
intersection/flexible transparent to
RULES1-based compatibility checks.
One way to look at it is to think
that this is an automatic way of handling
type parameters: automatic picking of
"interesting" bounds, and checking them against one another.
Note that `TypeIntersector.intersectTypes`
for `Int` and `T` where `T` is a type parameter
may return both `{Int & T}` or `null`
depending on `T`-s bounds. At the same time,
for type parameters `T` and `K` it will
always return `{T & K}`.
`ConeTypeIntersector.intersectTypes`, on the
other hand, will always return `{Int & T}`
irrespectively of the bounds. Meaning, the two
intersectors differ in corner cases.
`lowerBoundIfFlexible` call in `isLiterallyTypeParameter` is backed by
the `equalityOfFlexibleTypeParameters` test.
^KT-35134 #fixed-in-k2
^KT-22499 #fixed-in-k2
^KT-46383 #fixed-in-k2
In order to make resolution still work for members not available from
`Nothing`, we track the type without `Nothing?` and use that for
resolution instead.
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).