* `return` should only be added to the last statement if the return
type is not Unit
* If there is a `return` without an argument, then the expected return
type is Unit and the last expression is not a return argument (unless
it's an incomplete call, in which case it is inferred to return Unit;
this behavior is questionable, but inherited from K1)
* There should be a constraint on return arguments even if the expected
type is Unit, otherwise errors will be missed
* When the expected type is known, using the call completion results
writer is pointless (and probably subtly wrong).
^KT-54742 Fixed
- If too few or too many type arguments were provided, they were all
thrown away in `TypeArgumentMapping`,
`FirCallCompletionResultsWriterTransformer`, and `KtFirCallResolver`.
The fix handles type arguments of the wrong arity more gracefully.
- Note for `TypeArgumentMapping`: Excess type arguments are not needed
for candidate resolution. Excess type arguments are still resolved
due to the handling in `FirCallCompletionResultsWriterTransformer`.
- Post-processing in `AllCandidatesResolver`: When all candidates are
resolved in `AllCandidatesResolver.getAllCandidates`, the function
builds a FIR file. During that resolution, the
`generic<String, String>` call (in example
`functionCallWithTooFewTypeArguments.kt`) is correctly marked as
inapplicable, but the missing type argument is inferred as an error
type. `firFile` then contains a function call
`generic<String, String, ERROR>` instead of `generic<String, String>`.
This call is still marked as inapplicable. Despite that, the
*subsequent* resolution by
`bodyResolveComponents.callResolve.collectAllCandidates` disregards
the call's inapplicability and resolves successfully into an
applicable candidate. This is because `CandidateFactory` doesn't make
any guarantees for already inapplicable calls. The fix adds
post-processing to `AllCandidatesResolver` to preserve candidate
inapplicability.
- Most tests that this commit changes had slightly different results due
to type arguments becoming resolvable.
- `wrongNumberOfTypeArguments.kt` and
`wrongNumberOfArgumentsInTypeAliasConstructor.kt`:
`ConeDiagnostic.toFirDiagnostics` prefers specific errors. Because
`ARGUMENT_TYPE_MISMATCH` is specific and `INAPPLICABLE_CANDIDATE` is
not, only the former is reported. I see no reason to pass an illegally
typed argument in either test, so the change reduces the errors to
`INAPPLICABLE_CANDIDATE`.
- `typeAliasSamAdapterConstructors2.fir.kt`: See KT-55007.
- Disable `mismatchTypeParameters` JS backend test due to its handling
of excess type arguments. See KT-55250.
^KT-54980 fixed
The original idea was in resolving of annotation type ref using only
importing scopes and accepting or discarding that resolution result
depending on if this annotation is needed for compiler/plugins or not
But there is a problem that resolution of FirUserType with type resolver
is not a pure operation: type resolver transforms qualifier parts which
may contain type arguments, so if they were unresolved at the first
resolve, they will stay unresolved forever. To prevent this we will
deeply copy annotation type ref before first resolution
^KT-55286 Fixed
In K1 analogue of `K2_VISIBILITY_ERROR` is `K1_RUNTIME_ERROR`, so
candidates with `K2_VISIBILITY_ERROR` should win over innaplicable
candidates with `INAPPLICABLE`, `INAPPLICABLE_ARGUMENTS_MAPPING_ERROR`
or `INAPPLICABLE_WRONG_RECEIVER` applicability
This is needed to allow resolution to invisible symbols (and later
suppress error with `@Suppress("INVISIBLE_SYMBOL", "INVISIBLE_REFERENCE")`
^KT-55026 Fixed
^KT-55234
This is a temporary hack to avoid compiler crashes in some code that
uses builder inference, conditional early returns from lambdas, and
expected types in a certain way. It is not correct - dropping data flow
edges never is - but it is much easier to implement for now than a
proper fix.
This removes the need for hacks around the order in which function
call arguments are visited, fixes called-in-place lambda arguments
for augmented assignment operators, and makes CFG dumps a bit prettier.
The delegate is resolved in context-dependent mode and thus can be an
incomplete call; if there is no `provideDelegate` method to complete it,
the result is effectively `val x$delegate = y.id()` where `id` is
`fun <T> id(x: T) = x`, except we don't get a real node for `id` so the
DFA edges from lambdas in `y` go who knows where.
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.
It's also not a backwards jump in do-while, unless it's in the loop's
condition, which is a stupid "feature" IMO. As you can probably tell
from the comments added in this commit.
Previously, statuses of superclass which are not local was not ignored
Sometimes it worked in the IDE by calling lazyResolveToPhase
which is a violation of the lazy resolution contract
^KT-54890
Previously, statuses of superclass which are not local was not ignored
Sometimes it worked in the IDE by calling lazyResolveToPhase
which is a violation of the lazy resolution contract
^KT-54890
- Add a checker which ensures that property accesses have no explicit
type arguments. If an error on the property access's callee reference
already exists, the new error is not reported in favor of the existing
error, as the property access may have been intended to be a function
call.
- `complicatedLTGT.fir.kt`: The underlying parser issue is not yet
solved, which is why `x` is parsed as a property access with explicit
type arguments.
- `reservedExpressionSyntax` tests: This new check makes a lot of the
access expressions in these tests illegal, so valid lines have been
added and invalid lines appropriately marked with
`EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS` errors.
^KT-54978 fixed
- Allow 'lateinit' for inline classes which underlying type
is suitable for 'lateinit'
- K2: report all problems related to 'lateinit' modifier
^KT-55052: Fixed
The code was already duplicated between FirDataFlowAnalyzer and
FirReturnsImpliesAnalyzer, so might as well use the latter to slightly
speed up the former.
In theory, forking persistent flows should be cheap because of object
reuse, so the proposal here is to start from scratch and prove
redundancy of forks on a case-by-case basis. Something something better
safe than sorry.
^KT-28333 tag fixed-in-k2
^KT-28489 tag fixed-in-k2
callBothLambdas({ x = "..." }, { x is Int })
// the assignment always executes, so x is String | (String & Int);
// the latter is always a subtype of the former so it can be ignored