Quick quiz:
Q: In a CFG, what does `a -> b -> c -> d` mean?
A: `a`, then `b`, then `c`, then `d`.
Q: In a CFG, what does `a -> b -> d; a -> c -> d` mean?
A: `a`, then `b` or `c`, then `d`.
Q: So how do you encode "a, then (b, then c) or (c, then b), then d`?
A: You can't.
Problem is, you need to, because that's what `a; run2({ b }, { c }); d`
does when `run2` has a contract that it calls both its lambda arguments
in-place: `shuffle(listOf(block1, block2)).forEach { it() }` is a
perfectly valid implementation for it, as little sense as that makes.
So that's what union nodes solve. When a node implements
`UnionNodeMarker`, its inputs are interpreted as "all visited in some
order" instead of the normal "one of the inputs is visited".
Currently this is used for data flow. It *should* also be used for
control flow, but it isn't. But it should be. But that's not so easy.
BTW, `try` exit is NOT a union node; although lambdas in one branch can
be completed according to types' of lambdas in another, data does not
flow between the branches anyway (since we don't know how much of the
`try` executed before jumping into `catch`, and `catch`es are mutually
exclusive) so a `try` expression is more like `when` than a function
call with called-in-place-exactly-once arguments. The fact that
`exitTryExpression` used `processUnionOfArguments` in a weird way
should've hinted at that, but now we know for certain.
When serializing metadata for local delegated properties, we need to
find a valid container class where to put it, and where kotlin-reflect
will be able to find that metadata at runtime. Taking just the closest
class lexically doesn't work, because in the attached test, it is a
class for a lambda which does not have metadata and thus does not have a
way to store any extra information.
So, in 1663619606 we started to look for the closest "non-synthetic"
class to store this metadata. But apparently it was missed that script
is a valid container class. In the test, this meant that no
non-synthetic container classes were found to store the metadata, so we
falled back to using the closest class anyway (see `?: this` in
`rememberLocalProperty`), which turned out to be the lambda.
After this change, metadata for local delegated property in a lambda
will be stored in the script class, just like it's stored in the file
class in the non-script case.
#KT-55065 Fixed
Refactor the renderer, make BoundSymbolReferenceRenderer a static class
to prevent calling RenderIrElementVisitor's methods from it to avoid
infinite recursion in the future.
^KT-52677 Fixed
- Allow 'lateinit' for inline classes which underlying type
is suitable for 'lateinit'
- K2: report all problems related to 'lateinit' modifier
^KT-55052: Fixed
It's anyway safe to use avoidComprehensiveCheck = true because
during deserialization we're sure that we need DNN type because
it's been serialized as such.
This makes the `returns() implies` checker slightly cleaner, and also
fixes the case that I've missed where in RHS of `x ?:` type of `x` was
not set to `Nothing?`.
- Ensure that typed equals parameter's type is a star projection of
corresponding inline class
- Make possible to declare typed equals that returns 'Nothing'
- Forbid type parameters in typed equals operator declaration
^KT-54909 fixed
^KT-54910 fixed