[FIR] Get rid of obsolete TODOs in :fir:resolve module

This commit is contained in:
Dmitriy Novozhilov
2023-06-26 11:13:55 +03:00
committed by Space Team
parent e6fbcb5567
commit 213b39f213
22 changed files with 31 additions and 82 deletions
@@ -228,7 +228,6 @@ fun BodyResolveComponents.typeForQualifier(resolvedQualifier: FirResolvedQualifi
typeForQualifierByDeclaration(declaration, resultType, session)?.let { return it }
}
}
// TODO: Handle no value type here
return session.builtinTypes.unitType
}
@@ -349,7 +348,6 @@ private fun BodyResolveComponents.typeFromSymbol(symbol: FirBasedSymbol<*>): Fir
returnTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
}
is FirClassifierSymbol<*> -> {
// TODO: unhack
buildResolvedTypeRef {
source = null
type = symbol.constructType(emptyArray(), isNullable = false)
@@ -116,7 +116,7 @@ class FirSamResolver(
val syntheticFunctionSymbol = classSymbol.createSyntheticConstructorSymbol()
val newTypeParameters = firRegularClass.typeParameters.map { typeParameter ->
val declaredTypeParameter = typeParameter.symbol.fir // TODO: or really declared?
val declaredTypeParameter = typeParameter.symbol.fir
FirTypeParameterBuilder().apply {
source = declaredTypeParameter.source
moduleData = session.moduleData
@@ -143,7 +143,7 @@ class FirSamResolver(
)
for ((newTypeParameter, oldTypeParameter) in newTypeParameters.zip(firRegularClass.typeParameters)) {
val declared = oldTypeParameter.symbol.fir // TODO: or really declared?
val declared = oldTypeParameter.symbol.fir
newTypeParameter.bounds += declared.symbol.resolvedBounds.map { typeRef ->
buildResolvedTypeRef {
source = typeRef.source
@@ -134,7 +134,7 @@ abstract class AbstractConeCallConflictResolver(
hasVarargs = false,
numDefaults = 0,
isExpect = (variable as? FirProperty)?.isExpect == true,
isSyntheticMember = false // TODO
isSyntheticMember = false
)
}
@@ -149,7 +149,7 @@ abstract class AbstractConeCallConflictResolver(
hasVarargs = constructor.valueParameters.any { it.isVararg },
numDefaults = call.numDefaults,
isExpect = constructor.isExpect,
isSyntheticMember = false // TODO
isSyntheticMember = false
)
}
@@ -163,7 +163,7 @@ abstract class AbstractConeCallConflictResolver(
hasVarargs = function.valueParameters.any { it.isVararg },
numDefaults = call.numDefaults,
isExpect = function.isExpect,
isSyntheticMember = false // TODO
isSyntheticMember = false
)
}
@@ -226,7 +226,7 @@ abstract class AbstractConeCallConflictResolver(
(klass as? FirTypeParameterRefsOwner)?.typeParameters?.map { it.symbol.toLookupTag() }.orEmpty(),
emptyList(),
hasExtensionReceiver = false,
0, // TODO
0,
hasVarargs = false,
numDefaults = 0,
isExpect = (klass as? FirRegularClass)?.isExpect == true,
@@ -110,10 +110,7 @@ fun Candidate.resolveArgumentExpression(
)
else
preprocessCallableReference(argument, expectedType, context)
// TODO:!
is FirAnonymousFunctionExpression -> preprocessLambdaArgument(csBuilder, argument, expectedType, context, sink)
// TODO:!
//TODO: Collection literal
is FirWrappedArgumentExpression -> resolveArgumentExpression(
csBuilder,
argument.expression,
@@ -344,7 +341,6 @@ private fun checkApplicabilityForArgumentType(
) {
if (expectedType == null) return
// todo run this approximation only once for call
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(argumentTypeBeforeCapturing, expectedType, context.session)
fun subtypeError(actualExpectedType: ConeKotlinType): ResolutionDiagnostic {
@@ -422,7 +418,7 @@ private fun checkApplicabilityForArgumentType(
val nullableExpectedType = expectedType.withNullability(ConeNullability.NULLABLE, context.session.typeContext)
if (csBuilder.addSubtypeConstraintIfCompatible(argumentType, nullableExpectedType, position)) {
sink.reportDiagnostic(UnsafeCall(argumentType)) // TODO
sink.reportDiagnostic(UnsafeCall(argumentType))
} else {
csBuilder.addSubtypeConstraint(argumentType, expectedType, position)
sink.reportDiagnostic(InapplicableWrongReceiver(expectedType, argumentType))
@@ -496,8 +492,6 @@ private fun Candidate.getExpectedTypeWithSAMConversion(
): ConeKotlinType? {
if (candidateExpectedType.isSomeFunctionType(session)) return null
// TODO: resolvedCall.registerArgumentWithSamConversion(argument, SamConversionDescription(convertedTypeByOriginal, convertedTypeByCandidate!!))
val expectedFunctionType = context.bodyResolveComponents.samResolver.getFunctionTypeForPossibleSamType(candidateExpectedType)
?: return null
return runIf(argument.isFunctional(session, scopeSession, expectedFunctionType, context.returnTypeCalculator)) {
@@ -527,8 +521,6 @@ private fun getExpectedTypeWithImplicintIntegerCoercion(
}?.resolvedReturnType
}
// TODO: consider adding a check that argument could be converted to the parameter type (maybe difficult for platform types)
return argumentType?.withNullability(candidateExpectedType.nullability, session.typeContext)
}
@@ -210,10 +210,10 @@ private fun processConstructors(
}
}
//TODO: why don't we use declared member scope at this point?
scope?.processDeclaredConstructors {
if (includeInnerConstructors || !it.fir.isInner) {
processor(it)
scope?.processDeclaredConstructors {
if (includeInnerConstructors || !it.fir.isInner) {
processor(it)
}
}
}
@@ -38,7 +38,7 @@ internal object CreateFreshTypeVariableSubstitutorStage : ResolutionStage() {
// bad function -- error on declaration side
if (csBuilder.hasContradiction) {
sink.yieldDiagnostic(InapplicableCandidate) //TODO: auto report it
sink.yieldDiagnostic(InapplicableCandidate)
return
}
@@ -55,7 +55,6 @@ internal object CheckExplicitReceiverConsistency : ResolutionStage() {
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
val receiverKind = candidate.explicitReceiverKind
val explicitReceiver = callInfo.explicitReceiver
// TODO: add invoke cases
when (receiverKind) {
NO_EXPLICIT_RECEIVER -> {
if (explicitReceiver != null && explicitReceiver !is FirResolvedQualifier && !explicitReceiver.isSuperReferenceExpression()) {
@@ -71,7 +70,6 @@ internal object CheckExplicitReceiverConsistency : ResolutionStage() {
if (explicitReceiver == null) {
return sink.yieldDiagnostic(InapplicableWrongReceiver())
}
// Here we should also check additional invoke receiver
}
}
}
@@ -268,7 +266,6 @@ object CheckDslScopeViolation : ResolutionStage() {
context,
{ getDslMarkersOfImplicitReceiver(thisReference.boundSymbol, receiver.typeRef.coneType, context) }
) {
// TODO: is there better alternative?
// Here we rely on the fact that receiver expression of implicit receiver value can not be changed
// during resolution of one single call
it.receiverExpression == receiver
@@ -550,7 +547,6 @@ internal object CheckVisibility : CheckerStage() {
}
if (declaration is FirConstructor) {
// TODO: Should be some other form
val classSymbol = declaration.returnTypeRef.coneTypeUnsafe<ConeClassLikeType>().lookupTag.toSymbol(context.session)
if (classSymbol is FirRegularClassSymbol) {
@@ -621,10 +617,8 @@ internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionStage() {
}
internal object PostponedVariablesInitializerResolutionStage : ResolutionStage() {
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
val argumentMapping = candidate.argumentMapping ?: return
// TODO: convert type argument mapping to map [FirTypeParameterSymbol, FirTypedProjection?]
if (candidate.typeArgumentMapping is TypeArgumentMapping.Mapped) return
for (parameter in argumentMapping.values) {
if (!parameter.hasBuilderInferenceAnnotation(context.session)) continue
@@ -449,8 +449,9 @@ abstract class FirDataFlowAnalyzer(
return
}
// TODO: should be `getOrCreateIfRealAndUnchanged(flow from LHS, flow, leftOperand)`, otherwise the statement will
// be added even if the value has changed in the RHS. Currently the only previous node is the RHS.
// Ideally it should be `getOrCreateIfRealAndUnchanged(flow from LHS, flow, leftOperand)`, otherwise the statement will
// be added even if the value has changed in the RHS. Currently, the only previous node is the RHS.
// But seems like everything works and with current implementation
val leftOperandVariable = variableStorage.getOrCreateIfReal(flow, leftOperand)
val rightOperandVariable = variableStorage.getOrCreateIfReal(flow, rightOperand)
if (leftOperandVariable == null && rightOperandVariable == null) return
@@ -751,8 +752,6 @@ abstract class FirDataFlowAnalyzer(
// Otherwise if the result is non-null, then `b` executed, which implies `a` is not null
// and every statement from `b` holds.
val expressionVariable = variableStorage.getOrCreate(flow, safeCall)
// TODO? if the callee has non-null return type, then safe-call == null => receiver == null
// if (x?.toString() == null) { /* x == null */ }
// TODO? all new implications in previous node's flow are valid here if receiver != null
// (that requires a second level of implications: receiver != null => condition => effect).
flow.addAllConditionally(expressionVariable notEq null, node.lastPreviousNode.flow)
@@ -842,8 +841,6 @@ abstract class FirDataFlowAnalyzer(
if (conditionalEffects.isEmpty()) return
val arguments = qualifiedAccess.orderedArguments(callee) ?: return
// TODO: should be `getOrCreateIfRealAndUnchanged(last flow of argument i, flow, it)`
// ^-- good luck finding that
val argumentVariables = Array(arguments.size) { i -> arguments[i]?.let { variableStorage.getOrCreateIfReal(flow, it) } }
if (argumentVariables.all { it == null }) return
@@ -899,7 +896,6 @@ abstract class FirDataFlowAnalyzer(
if (property.isLocal || property.isVal) {
exitVariableInitialization(flow, assignment.rValue, property, assignment.lValue, hasExplicitType = false)
} else {
// TODO: add unstable smartcast for non-local var
val variable = variableStorage.getRealVariableWithoutUnwrappingAlias(flow, assignment)
if (variable != null) {
logicSystem.recordNewAssignment(flow, variable, context.newAssignmentIndex())
@@ -946,7 +942,7 @@ abstract class FirDataFlowAnalyzer(
if (isAssignment) {
// `propertyVariable` can be an alias to `initializerVariable`, in which case this will add
// a redundant type statement which is fine...probably. TODO: store initial type within the variable?
// a redundant type statement which is fine...probably
flow.addTypeStatement(flow.unwrapVariable(propertyVariable) typeEq initializer.typeRef.coneType)
}
}
@@ -137,7 +137,6 @@ internal class FirLocalVariableAssignmentAnalyzer {
val (info, prohibitSmartCasts) = enterScope(klass.symbol, klass is FirAnonymousObject)
if (klass is FirAnonymousObject && info != null) {
// Assignments in initializers and methods invalidate smart casts in other members.
// TODO: initializers shouldn't invalidate smart casts in themselves.
prohibitSmartCasts.addAll(info.assignedInside)
}
}
@@ -269,7 +269,7 @@ class ControlFlowGraphBuilder {
// Postponed exit node was needed so we could create lambda->call edges without having the subgraph ready. If it
// doesn't exist, then we probably can't do that anymore, and the lambda won't be called-in-place in the CFG.
// TODO: verify & enable this assertion?
//assert(invocationKind?.canBeVisited() != true) { "no exit node for calledInPlace($invocationKind) lambda" }
// assert(invocationKind?.canBeVisited() != true) { "no exit node for calledInPlace($invocationKind) lambda" }
return Triple(exitNode, null, graph)
}
@@ -310,7 +310,6 @@ class ControlFlowGraphBuilder {
} else {
for ((exit, kind) in currentLevelExits) {
// Do not add data flow edges from non-terminating lambdas; there is no "dead data flow only"
// `EdgeKind`. TODO?
if (kind.usedInCfa || !exit.isDead) {
// Since `node` is a union node, it is dead iff any input is dead. For once, `propagateDeadness`
// semantics are correct without an `updateDeadStatus`.
@@ -397,7 +396,6 @@ class ControlFlowGraphBuilder {
}
val localClassEnterNode = when {
// TODO: enum classes cannot be local so this is mostly fine, but it looks hacky. Maybe handle FirEnumEntry?
klass is FirAnonymousObject && klass.classKind != ClassKind.ENUM_ENTRY -> createAnonymousObjectEnterNode(klass)
// Local classes are only initialized on first use, so they look pretty much like named functions:
// control flow enters here and never leaves, and assignments invalidate smart casts.
@@ -511,14 +509,8 @@ class ControlFlowGraphBuilder {
addEdge(enterNode, exitNode, preferredKind = EdgeKind.DeadForward, propagateDeadness = false)
}
// TODO: Here we're assuming that the methods are called after the object is constructed, which is really not true
// (init blocks can call them). But FE1.0 did so too, hence the following code compiles and prints 0:
// val x: Int
// object {
// fun bar() = x
// init { x = bar() }
// }
// println(x)
// Here we're assuming that the methods are called after the object is constructed, which is really not true
// But it's fine, since Kotlin intentionally does not support analysis of "leaked this" bugs
for (graph in calledLater) {
addEdgeToSubGraph(exitNode, graph.enterNode)
}
@@ -534,7 +526,6 @@ class ControlFlowGraphBuilder {
return createAnonymousObjectExpressionExitNode(anonymousObjectExpression).also {
val exitNode = klass.controlFlowGraphReference?.controlFlowGraph?.exitNode
// TODO: `lastNode` should be `AnonymousObjectEnterNode`, but delegate properties are somewhat broken.
if (exitNode != null && lastNode is AnonymousObjectEnterNode) {
addEdge(exitNode, it)
// Fake edge to enforce ordering.
@@ -879,7 +870,6 @@ class ControlFlowGraphBuilder {
// These edges should really be from `enterTryMainBlockNode`, but there is no practical difference
// so w/e. In fact, `enterTryExpressionNode` is just 100% redundant.
// TODO: this is more or less `addExceptionEdgesFrom(enterTryExpressionNode)`. Hmm.
for (catchEnterNode in catchNodes.top()) {
addEdge(enterTryExpressionNode, catchEnterNode)
}
@@ -904,8 +894,6 @@ class ControlFlowGraphBuilder {
addEdge(node, nextNode, propagateDeadness = false)
for (catchEnterNode in catchNodes.pop().asReversed()) {
catchBlocksInProgress.push(catchEnterNode)
// TODO: figure out if this edge is correct.
// try { x = /* something non-throwing like variable read */ } catch (...) { /* can assume assignment didn't happen? */ }
addEdge(node, catchEnterNode, propagateDeadness = false)
}
return node
@@ -915,7 +903,6 @@ class ControlFlowGraphBuilder {
val catchEnterNode = catchBlocksInProgress.pop()
assert(catchEnterNode.fir == catch)
if (tryExitNodes.top().fir.finallyBlock != null) {
// TODO: not sure this does anything?
addEdge(catchEnterNode, finallyEnterNodes.top(), propagateDeadness = false, label = UncaughtExceptionPath)
}
lastNodes.push(catchEnterNode)
@@ -946,10 +933,6 @@ class ControlFlowGraphBuilder {
val exitNode = createFinallyBlockExitNode(enterNode.fir)
popAndAddEdge(exitNode)
addEdge(exitNode, tryExitNode, isDead = enterNode.allNormalInputsAreDead)
// TODO: there should also be edges to outer catch blocks? Control flow can go like this:
// try { try { throw E2() } catch (e: E1) { } finally { } } catch (e: E2) { }
// \-----------------------------^ \-----------------^
// Wait, that's just `addExceptionEdgesFrom(exitNode)` again!
val nextExitLevel = levelOfNextExceptionCatchingGraph()
val nextFinally = finallyEnterNodes.topOrNull()?.takeIf { it.level > nextExitLevel }
if (nextFinally != null) {
@@ -984,7 +967,12 @@ class ControlFlowGraphBuilder {
for (node in nodes) {
when {
// TODO: this check is imprecise and can add redundant edges:
// x@{ try { return@x } finally {}; try {} finally { /* return@x target is in nonDirectJumps */ }
// x@{
// try {
// return@x
// } finally {}
// }
// try {} finally { /* return@x target is in nonDirectJumps */ }
node.level < minLevel || node !in nonDirectJumps -> continue
// TODO: if the input to finally with that label is dead, then so should be the exit probably
node.returnPathIsBackwards -> addBackEdge(this, node, label = node)
@@ -1038,7 +1026,7 @@ class ControlFlowGraphBuilder {
// this is a workaround to make function call dead when call is completed _after_ building its node in the graph
// this happens when completing the last call in try/catch blocks
// todo this doesn't make fully 'right' Nothing node (doesn't support going to catch and pass through finally)
// TODO: this doesn't make fully 'right' Nothing node (doesn't support going to catch and pass through finally)
// because doing those afterwards is quite challenging
// it would be much easier if we could build calls after full completion only, at least for Nothing calls
// @returns `true` if node actually returned Nothing
@@ -1164,7 +1152,6 @@ class ControlFlowGraphBuilder {
fun enterFakeExpression(): FakeExpressionEnterNode {
// Things like annotations and `contract { ... }` use normal call resolution, but aren't real expressions
// and are never evaluated. We'll push all nodes created in the process into a stub graph, then throw it away.
// TODO: don't waste time creating the nodes in the first place
return enterGraph(null, "<compile-time expression graph>", ControlFlowGraph.Kind.FakeCall) {
createFakeExpressionEnterNode() to createFakeExpressionEnterNode()
}
@@ -1188,7 +1175,6 @@ class ControlFlowGraphBuilder {
// ----------------------------------- Block -----------------------------------
fun enterInitBlock(initBlock: FirAnonymousInitializer): InitBlockEnterNode {
// TODO: questionable moment that we should pass data flow from init to init
return enterGraph(initBlock, "init block", ControlFlowGraph.Kind.ClassInitializer) {
createInitBlockEnterNode(it) to createInitBlockExitNode(it)
}.also { addEdgeIfLocalClassMember(it) }
@@ -125,8 +125,6 @@ class FirControlFlowGraphRenderVisitor(
val controlFlowGraph = (controlFlowGraphReference as? FirControlFlowGraphReferenceImpl)?.controlFlowGraph ?: return
if (controlFlowGraph.isSubGraph) return
// TODO: nodes are already in a topological order, but grouping nodes into clusters requires something more.
// But what exactly? And is there a way to do `renderNodes` differently so that any topological order is ok?
val nodes = DFS.topologicalOrder(listOf(controlFlowGraph.enterNode)) { it.followingNodes }
.associateWithTo(linkedMapOf()) { nodeCounter++ }
printer.renderNodes(nodes)
@@ -233,7 +233,7 @@ class ConstraintSystemCompleter(components: BodyResolveComponents, private val c
is ResolvedCallableReferenceAtom ->
argument.reviseExpectedType(revisedExpectedType)
is LambdaWithTypeVariableAsExpectedTypeAtom ->
argument.transformToResolvedLambda(c.getBuilder(), resolutionContext, revisedExpectedType, null /*TODO()*/)
argument.transformToResolvedLambda(c.getBuilder(), resolutionContext, revisedExpectedType)
else -> throw IllegalStateException("Unsupported postponed argument type of $argument")
}
@@ -338,7 +338,6 @@ class ConstraintSystemCompleter(components: BodyResolveComponents, private val c
fun ConeTypeVariable?.toTypeConstructor(): TypeConstructorMarker? =
this?.typeConstructor?.takeIf { it in notFixedTypeVariables.keys }
// TODO: non-top-level variables?
fun PostponedAtomWithRevisableExpectedType.collectNotFixedVariables() {
revisedExpectedType?.lowerBoundIfFlexible()?.asArgumentList()?.let { typeArgumentList ->
for (typeArgument in typeArgumentList) {
@@ -402,7 +401,7 @@ class ConstraintSystemCompleter(components: BodyResolveComponents, private val c
TypeVariableDirectionCalculator.ResolveDirection.UNKNOWN
)
val variable = variableWithConstraints.typeVariable
c.fixVariable(variable, resultType, ConeFixVariableConstraintPosition(variable)) // TODO: obtain atom for diagnostics
c.fixVariable(variable, resultType, ConeFixVariableConstraintPosition(variable))
}
companion object {
@@ -92,7 +92,7 @@ abstract class FirInferenceSessionForChainedResolve(
lowerSubstituted,
upperSubstituted,
this.constraintKind,
ConeBuilderInferenceSubstitutionConstraintPosition(this) // TODO
ConeBuilderInferenceSubstitutionConstraintPosition(this)
)
}
@@ -63,8 +63,6 @@ class PostponedArgumentsAnalyzer(
analyzeLambda(c, argument.transformToResolvedLambda(c.getBuilder(), resolutionContext), candidate, completionMode)
is ResolvedCallableReferenceAtom -> processCallableReference(argument, candidate)
// is ResolvedCollectionLiteralAtom -> TODO("Not supported")
}
}
@@ -412,7 +412,6 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
userTypeRef: FirUserTypeRef,
qualifierPartArgumentsCount: Int?
): ConeErrorType? {
// TODO: It should be TYPE_ARGUMENTS_NOT_ALLOWED diagnostics when parameterClass is null
val actualTypeParametersCount = getActualTypeParametersCount(parameterClass ?: symbol.fir)
if (qualifierPartArgumentsCount == null || actualTypeParametersCount != qualifierPartArgumentsCount) {
@@ -163,8 +163,6 @@ private class FirApplySupertypesTransformer(
private fun applyResolvedSupertypesToClass(firClass: FirClass) {
if (firClass.superTypeRefs.any { it !is FirResolvedTypeRef || it is FirImplicitBuiltinTypeRef }) {
val supertypeRefs = getResolvedSupertypeRefs(firClass)
// TODO: Replace with an immutable version or transformer
firClass.replaceSuperTypeRefs(supertypeRefs)
}
@@ -196,7 +194,6 @@ private class FirApplySupertypesTransformer(
"Expected single supertypeRefs, but found ${supertypeRefs.size} in ${typeAlias.symbol.classId}"
}
// TODO: Replace with an immutable version or transformer
typeAlias.replaceExpandedTypeRef(supertypeRefs[0])
return typeAlias
}
@@ -521,7 +518,6 @@ open class FirSupertypeResolverVisitor(
expandedTypeRef: FirTypeRef,
resolveRecursively: Boolean,
): List<FirResolvedTypeRef> {
// TODO: this if is a temporary hack for built-in types (because we can't load file for them)
if (expandedTypeRef is FirResolvedTypeRef) {
return listOf(expandedTypeRef)
}
@@ -41,7 +41,7 @@ internal fun remapArgumentsWithVararg(
var indexAfterVarargs = argumentList.size
val newArgumentMapping = linkedMapOf<FirExpression, FirValueParameter>()
val varargArgument = buildVarargArgumentsExpression {
//todo ideally we should use here a source from the use-site and not from the declaration-site
// TODO: ideally we should use here a source from the use-site and not from the declaration-site
this.varargElementType = varargParameterTypeRef.withReplacedConeType(varargElementType, KtFakeSourceElementKind.VarargArgument)
this.typeRef = varargParameterTypeRef.withReplacedConeType(varargArrayType, KtFakeSourceElementKind.VarargArgument)
var startOffset = Int.MAX_VALUE
@@ -434,8 +434,7 @@ open class FirDeclarationsResolveTransformer(
return variable
}
// TODO: This enum might actually be a boolean (resolve setter/don't resolve setter)
// But for some reason, in IDE there's a need to resolve setter's parameter types on the implicit-resolution stage
// In IDE there's a need to resolve setter's parameter types on the implicit-resolution stage
// See ad183434137939a0c9eeea2f7df9ef522672a18e commit.
// But for delegate inference case, we don't need both body of the setter and its parameter resolved (SKIP mode)
private enum class SetterResolutionMode {
@@ -630,7 +629,6 @@ open class FirDeclarationsResolveTransformer(
return context.withSimpleFunction(simpleFunction, session) {
doTransformTypeParameters(simpleFunction)
// TODO: I think it worth creating something like runAllPhasesForLocalFunction
if (containingDeclaration != null && containingDeclaration !is FirClass) {
// For class members everything should be already prepared
prepareSignatureForBodyResolve(simpleFunction)
@@ -104,7 +104,6 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
qualifiedAccessExpression.transformTypeArguments(transformer, ResolutionMode.ContextIndependent)
var result = when (val callee = qualifiedAccessExpression.calleeReference) {
// TODO: there was FirExplicitThisReference
is FirThisReference -> {
val labelName = callee.labelName
val implicitReceiver = implicitReceiverStack[labelName]
@@ -301,7 +301,6 @@ abstract class FirAbstractContractResolveTransformerDispatcher(
}
private fun <T : FirContractDescriptionOwner> transformOwnerOfErrorContract(owner: T): T {
// TODO
dataFlowAnalyzer.exitContractDescription()
return owner
}
@@ -244,7 +244,6 @@ abstract class AbstractFirSpecificAnnotationResolveTransformer(
annotationCall.replaceAnnotationTypeRef(transformedAnnotationType)
annotationCall.replaceAnnotationResolvePhase(FirAnnotationResolvePhase.CompilerRequiredAnnotations)
// TODO: what if we have type alias here?
if (transformedAnnotationType.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.classId in REQUIRED_ANNOTATIONS_WITH_ARGUMENTS) {
argumentsTransformer.transformAnnotation(annotationCall, ResolutionMode.ContextDependent)
}
@@ -77,7 +77,6 @@ private fun doCreateImportingScopes(
else ->
FirPackageMemberScope(file.packageFqName, session, excludedNames = excludedNamesInPackage)
},
// TODO: explicit simple importing scope should have highest priority (higher than inner scopes added in process)
FirExplicitSimpleImportingScope(file.imports, session, scopeSession)
)
}