You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Error message for TypeForm arguments with a single unresolvable forward reference is misleading #21695
When passing a single stringified type expression to a function accepting a TypeForm argument, which cannot be fully resolved, due to e.g. a missing import, we get an arg-type error instead of an error, telling us why the type expression is invalid.
mypy should emit a name-error for Unresolvable, since it was never defined. The given example is probably the most controversial case though, since someone may actually accidentally be passing an invalid string literal, but the same thing happens for less controversial cases like "list[Unresolvable]". But I think either way it makes more sense to treat the given string literal as a type expression and emit the same errors you would emit if you saw the same string literal in an annotation.
Actual Behavior
error: Argument 1 to "foo" has incompatible type "str"; expected "TypeForm[Never]" [arg-type]
This error does not help us solve the problem in our code at all.
Instead of an error, telling us why the type expression is invalid.
By the time the type checker pass notices that the first parameter of foo("Unresolvable") wants a TypeForm, any errors related to attempting to parse "Unresolvable" (done in the earlier semantic analyzer pass) have been thrown away. It's not really feasible (for performance/memory reasons) to preserve those errors for rare situations like this where they're desired later in the type checker pass.
Workaround
Replace foo("Unresolvable") with foo(TypeForm("Unresolvable")) to get a descriptive error.
Full Fix
Make it possible to parse stringified type forms in the type checker pass, not just the semantic analyzer pass. This would be a high-effort change. If it could be pulled off, it would eliminate the need to parse type forms in the semantic analyzer pass at all, which would eliminate all the related performance issues that I'm trying to fix piecemeal with followup PRs like #21596 .
@davidfstr I think we should still be able to improve the UX without hurting performance by emitting a different error when a string literal is passed into a TypeForm argument than the standard arg-type error for the type mismatch str against TypeForm. It doesn't have to be the actual reason for why the forward reference failed to be interpreted as a TypeForm during semantic analysis, it's good enough if the error tells users that some error may have occurred when trying to resolve that literal as a forward reference, and to add a hint that tells users to wrap the forward reference in a TypeForm call if they want to get a more specific error. The error category can probably stay arg-type, since we can't know for sure if the string literal was supposed to be a forward reference, or if they just got the argument order wrong and it actually was supposed to just be a string literal. Although a dedicated error category or misc could also make sense.
This should be a reasonable stop-gap measure until we can implement a full fix. Although even with the full fix it might be more appropriate to emit the error in the TypeForm only as a hint for a potential cause for why this argument is invalid and keep the error otherwise the same as suggested.
Activity
ilevkivskyi commentedon Jul 10, 2026
cc @davidfstr in case you are interested.
davidfstr commentedon Jul 10, 2026
By the time the type checker pass notices that the first parameter of
foo("Unresolvable")wants a TypeForm, any errors related to attempting to parse"Unresolvable"(done in the earlier semantic analyzer pass) have been thrown away. It's not really feasible (for performance/memory reasons) to preserve those errors for rare situations like this where they're desired later in the type checker pass.Workaround
Replace
foo("Unresolvable")withfoo(TypeForm("Unresolvable"))to get a descriptive error.Full Fix
Make it possible to parse stringified type forms in the type checker pass, not just the semantic analyzer pass. This would be a high-effort change. If it could be pulled off, it would eliminate the need to parse type forms in the semantic analyzer pass at all, which would eliminate all the related performance issues that I'm trying to fix piecemeal with followup PRs like #21596 .
Daverball commentedon Sep 22, 2026
@davidfstr I think we should still be able to improve the UX without hurting performance by emitting a different error when a string literal is passed into a
TypeFormargument than the standardarg-typeerror for the type mismatchstragainstTypeForm. It doesn't have to be the actual reason for why the forward reference failed to be interpreted as aTypeFormduring semantic analysis, it's good enough if the error tells users that some error may have occurred when trying to resolve that literal as a forward reference, and to add a hint that tells users to wrap the forward reference in aTypeFormcall if they want to get a more specific error. The error category can probably stayarg-type, since we can't know for sure if the string literal was supposed to be a forward reference, or if they just got the argument order wrong and it actually was supposed to just be a string literal. Although a dedicated error category ormisccould also make sense.This should be a reasonable stop-gap measure until we can implement a full fix. Although even with the full fix it might be more appropriate to emit the error in the
TypeFormonly as a hint for a potential cause for why this argument is invalid and keep the error otherwise the same as suggested.