[FIR] Get rid of obsolete TODOs in :fir:resolve module
This commit is contained in:
committed by
Space Team
parent
e6fbcb5567
commit
213b39f213
@@ -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
|
||||
|
||||
+4
-4
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -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)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+4
-8
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+10
-24
@@ -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) }
|
||||
|
||||
-2
@@ -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)
|
||||
|
||||
+2
-3
@@ -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 {
|
||||
|
||||
+1
-1
@@ -92,7 +92,7 @@ abstract class FirInferenceSessionForChainedResolve(
|
||||
lowerSubstituted,
|
||||
upperSubstituted,
|
||||
this.constraintKind,
|
||||
ConeBuilderInferenceSubstitutionConstraintPosition(this) // TODO
|
||||
ConeBuilderInferenceSubstitutionConstraintPosition(this)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
-2
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -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) {
|
||||
|
||||
-4
@@ -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)
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-3
@@ -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)
|
||||
|
||||
-1
@@ -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]
|
||||
|
||||
-1
@@ -301,7 +301,6 @@ abstract class FirAbstractContractResolveTransformerDispatcher(
|
||||
}
|
||||
|
||||
private fun <T : FirContractDescriptionOwner> transformOwnerOfErrorContract(owner: T): T {
|
||||
// TODO
|
||||
dataFlowAnalyzer.exitContractDescription()
|
||||
return owner
|
||||
}
|
||||
|
||||
-1
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user