PY-76899 Conformance test failure: dataclasses_transform_field

GitOrigin-RevId: 83dbf7add2b63b592a68e23182c22090f74f4f5d
This commit is contained in:
Azim Akhmadjonov
2026-02-04 11:15:02 +00:00
committed by intellij-monorepo-bot
parent c79fc0d56e
commit d3306b960f
8 changed files with 142 additions and 4 deletions

View File

@@ -12,6 +12,7 @@ import com.jetbrains.python.codeInsight.PyDataclassParameters.Type
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil
import com.jetbrains.python.psi.LanguageLevel
import com.jetbrains.python.psi.PyCallExpression
import com.jetbrains.python.psi.PyClass
import com.jetbrains.python.psi.PyDecoratable
import com.jetbrains.python.psi.PyDecorator
@@ -25,9 +26,11 @@ import com.jetbrains.python.psi.PyQualifiedNameOwner
import com.jetbrains.python.psi.PyReferenceExpression
import com.jetbrains.python.psi.PyTargetExpression
import com.jetbrains.python.psi.PyUtil
import com.jetbrains.python.psi.impl.IntentionalUnstubbing
import com.jetbrains.python.psi.impl.PyEvaluator
import com.jetbrains.python.psi.impl.StubAwareComputation
import com.jetbrains.python.psi.impl.mapArguments
import com.jetbrains.python.psi.impl.selectMatchingOverload
import com.jetbrains.python.psi.impl.stubs.PyDataclassFieldStubImpl
import com.jetbrains.python.psi.impl.stubs.PyDataclassStubImpl
import com.jetbrains.python.psi.resolve.PyResolveContext
@@ -40,6 +43,7 @@ import com.jetbrains.python.psi.types.PyCallableParameterImpl
import com.jetbrains.python.psi.types.PyCallableTypeImpl
import com.jetbrains.python.psi.types.PyClassType
import com.jetbrains.python.psi.types.TypeEvalContext
import com.jetbrains.python.pyi.PyiUtil
object PyDataclassNames {
@@ -780,13 +784,25 @@ fun resolveDataclassFieldParameters(
else -> null
}
if (fieldSpecifierCallable == null) return null
val shouldMatchOverloads = PyiUtil.getOverloads(fieldSpecifierCallable, context).isNotEmpty()
val resolvedCallable = if (shouldMatchOverloads) {
val callExpression = IntentionalUnstubbing.onFileOf(field) {
field.findAssignedValue() as? PyCallExpression
}
val overload = callExpression?.let { fieldSpecifierCallable.selectMatchingOverload(it, context) }
overload ?: fieldSpecifierCallable
}
else {
fieldSpecifierCallable
}
return PyDataclassFieldParameters(
hasDefault = fieldStub?.hasDefault() ?: false,
hasDefaultFactory = fieldStub?.hasDefaultFactory() ?: false,
// TODO Should we delegate to dataclass parameters init here?
// TODO support overloading init with Literal types
initValue = fieldStub?.initValue() ?: getArgumentDefault("init", fieldSpecifierCallable) ?: true,
kwOnly = fieldStub?.kwOnly() ?: getArgumentDefault("kw_only", fieldSpecifierCallable) ?: dataclassParams.kwOnly,
initValue = fieldStub?.initValue() ?: getArgumentDefault("init", resolvedCallable) ?: true,
kwOnly = fieldStub?.kwOnly() ?: getArgumentDefault("kw_only", resolvedCallable) ?: dataclassParams.kwOnly,
alias = fieldStub?.alias,
)
}

View File

@@ -1395,6 +1395,39 @@ private fun List<PyCallableParameter>.filterExplicitParameters(
return subList(min(implicitOffset, size), size)
}
/**
* Returns the overload declaration of this function that best matches the given call expression,
* or null if no overload matches or overloads are unavailable in the current context.
*/
@ApiStatus.Internal
fun PyFunction.selectMatchingOverload(
callExpression: PyCallExpression,
context: TypeEvalContext
): PyFunction? {
val overloads = PyiUtil.getOverloads(this, context)
if (overloads.isEmpty()) return null
val arguments = callExpression.getArguments(this)
val matchingOverloads = overloads.filter { it.matchesByArgumentTypes(callExpression, context) }
if (matchingOverloads.isEmpty()) {
return null
}
if (matchingOverloads.size == 1) {
return matchingOverloads[0]
}
val someArgumentsHaveUnknownType = arguments.any { argument ->
context.getType(argument) == null
}
if (someArgumentsHaveUnknownType) {
return null
}
return matchingOverloads.firstOrNull()
}
fun PyExpression.canQualifyAnImplicitName(): Boolean {
if (this !is PyCallExpression) return true
val callee = callee