Type Checker Rule Comparison Table¶
| scenario | basedpyright | ty/ruff1 | pyrefly |
|---|---|---|---|
| property type mismatch | reportPropertyTypeMismatch |
issue | issue |
| invalid member access on functions | reportFunctionMemberAccess |
unresolved-attribute |
missing-attribute |
| module import not found | reportMissingImports |
unresolved-import |
missing-import |
| import attribute from module not found | reportAttributeAccessIssue |
unresolved-import |
missing-module-attribute |
| wrong argument type in function call | reportArgumentType |
invalid-argument-type |
bad-argument-type |
| wrong default value type in function call | reportArgumentType |
invalid-parameter-default |
bad-function-definition |
assert_type failure |
reportAssertTypeFailure |
type-assertion-failure, assert-type-unspellable-subtype |
assert-type |
| bad assignment type | reportAssignmentType |
invalid-assignment, invalid-declaration |
bad-assignment |
| unpack to wrong number of variables | reportAssignmentType |
invalid-assignment |
bad-unpacking |
| bad attribute access | reportAttributeAccessIssue,reportOptionalMemberAccess |
unresolved-attribute |
missing-attribute, no-access |
| instantiate abstract class | reportAbstractUsage |
issue | bad-instantiation |
abstract @classmethod call |
reportAbstractUsage |
call-abstract-method |
abstract-method-call |
@deprecated usage |
reportDeprecated |
deprecated |
deprecated |
| incompatible method override | reportIncompatibleMethodOverride |
invalid-method-override |
bad-override, bad-override-param-name |
| conflicting members in multiple inheritance | reportIncompatibleMethodOverride |
invalid-method-override |
inconsistent-inheritance |
| incompatible attribute override | reportIncompatibleVariableOverride |
invalid-attribute-override3, invalid-typed-dict-field |
bad-override-mutable-attribute |
| inconsistent overload | reportInconsistentOverload |
invalid-overload |
inconsistent-overload |
| overlapping overload | reportOverlappingOverload |
issue | issue |
| no overload implementation | reportNoOverloadImplementation |
invalid-overload |
invalid-overload |
| only one overload | reportInconsistentOverload |
invalid-overload |
invalid-overload |
| not subscriptable | reportIndexIssue, reportOptionalSubscript |
not-subscriptable |
unsupported-operation |
| index out of range | reportGeneralTypeIssues |
index-out-of-bounds |
bad-index |
| invalid type argument usage | reportInvalidTypeArguments |
invalid-type-arguments |
bad-specialization |
| invalid type form | reportInvalidTypeForm |
invalid-type-form |
invalid-annotation, invalid-literal, invalid-type-alias,not-a-type |
| typevar only used once in signature | reportInvalidTypeVarUse |
issue | issue |
| typevar may go unsolved | reportInvalidTypeVarUse |
issue | issue |
| stub exists but no source | reportMissingModuleSource |
issue | missing-source, missing-source-for-stubs |
| no type annotation on parameter | reportMissingParameterType, reportUnknownParameterType |
ANN001 |
implicit-any-parameter |
| source exists but no stubs | reportMissingTypeStubs |
issue | untyped-import |
| invalid usage of operator | reportOperatorIssue, reportOptionalOperand |
unsupported-operator |
unsupported-operation |
| undefined variable | reportUndefinedVariable, reportUnknownVariableType |
unresolved-reference |
unknown-name |
variable used after being del'd |
reportUnboundVariable |
unresolved-reference |
unbound-name |
| conditionally bound variable | reportPossiblyUnboundVariable |
possibly-unresolved-reference |
unbound-name |
| private member usage | reportAttributeAccessIssue |
unresolved-attribute |
missing-attribute |
| protected member usage | reportPrivateUsage |
SLF001 |
issue |
| incorrect return type | reportReturnType |
invalid-return-type |
bad-return |
| incorrect yield type | reportReturnType |
invalid-yield |
invalid-yield |
yield outside function |
no code | invalid-syntax |
invalid-yield |
yield from non-Iterable |
reportGeneralTypeIssues |
not-iterable |
invalid-yield |
| uninitialized instance variable | reportUninitializedInstanceVariable |
issue | implicitly-defined-attribute4 |
| argument has an unknown type | reportUnknownArgumentType |
issue | issue |
| member has an unknown type | reportUnknownMemberType |
issue | implicit-any-attribute15 |
| useless cast | reportUnnecessaryCast |
redundant-cast |
redundant-cast |
| unawaited coroutine | reportUnusedCoroutine |
unused-awaitable |
unused-coroutine |
| circular imports | reportImportCycles |
issue | issue |
| unused import | reportUnusedImport |
F401 |
hint5 |
| unused class | reportUnusedClass |
issue | 5 |
| unused function | reportUnusedFunction |
issue | 5 |
| unused variable | reportUnusedVariable |
issue | 5 |
| duplicate import | reportDuplicateImport |
F811 |
5 |
| wildcard import | reportWildcardImportFromLibrary |
F403 |
5 |
| missing mandatory argument to callable | reportCallIssue |
missing-argument |
missing-argument |
| too many positional arguments to callable | reportCallIssue |
too-many-positional-arguments |
bad-argument-count, unexpected-positional-argument |
| positional argument passed as keyword arg | reportCallIssue |
positional-only-parameter-as-kwarg |
unexpected-keyword |
| unknown keyword arg to callable | reportCallIssue |
unknown-argument |
unexpected-keyword |
| keyword arg already assigned as positional arg | reportCallIssue |
parameter-already-assigned |
bad-keyword-argument |
| keyword arg already assigned as keyword arg | reportCallIssue |
invalid-syntax |
parse-error |
| possible unpack of already be assigned keyword arg | reportCallIssue |
parameter-already-assigned |
potential-bad-keyword-argument |
| no matching overload | reportCallIssue |
no-matching-overload |
no-matching-overload, incompatible-overload-residual |
| call non-callable | reportCallIssue, reportOptionalCall |
call-non-callable |
not-callable |
| iterate non-iterable | reportGeneralTypeIssues, reportOptionalIterable |
not-iterable |
not-iterable |
with on non-context manager |
reportGeneralTypeIssues, reportOptionalContextManager |
invalid-context-manager |
bad-context-manager |
| redeclaration with same type | reportRedeclaration |
issue | redefinition |
| redeclaration with different types | reportRedeclaration |
conflicting-declarations |
redefinition |
NotRequired access in TypedDict |
reportTypedDictNotRequiredAccess |
issue | not-required-key-access |
| untyped decorator | reportUntypedFunctionDecorator, reportUntypedClassDecorator |
issue | untyped-class-decorator, untyped-function-decorator14 |
| untyped base class | reportUntypedBaseClass |
unsupported-base |
issue |
| untyped namedtuple | reportUntypedNamedTuple |
PYI024 |
5 |
| type comment usage | reportTypeCommentUsage |
PYI033 |
5 |
| implicit re-export | reportPrivateImportUsage, reportPrivateLocalImportUsage |
issue | implicit-reexport |
| all-caps constant re-assignment | reportConstantRedefinition |
issue | issue |
Final re-assignment |
reportGeneralTypeIssues |
invalid-assignment |
bad-assignment |
Final without initial value |
reportGeneralTypeIssues |
final-without-value |
invalid-annotation |
| inconsistent constructor | reportInconsistentConstructor |
issue | issue |
missing super call |
reportMissingSuperCall |
issue | missing-super-call |
invalid super call |
reportGeneralTypeIssues |
unavailable-implicit-super-arguments |
invalid-super-call |
invalid super call with explicit arguments |
reportArgumentType |
invalid-super-argument |
invalid-super-call, invalid-argument |
| invalid string escape | reportInvalidStringEscapeSequence |
W605 |
5 |
| unknown lambda type | reportUnknownLambdaType |
issue | implicit-any-lambda |
| missing type argument | reportMissingTypeArgument |
missing-type-argument |
implicit-any-type-argument |
| mutable default value for arguemnt | reportCallInDefaultInitializer |
B006 |
5 |
| unnecessary conditions | reportUnnecessaryIsInstance |
issue | redundant-condition9 |
| unnecessary comparison | reportUnnecessaryComparison |
issue | incompatible-comparison, unnecessary-comparison9 |
unnecessary in |
reportUnnecessaryContains |
unsupported-operator |
issue |
| wrong name for first method parameter | reportSelfClsParameterName |
N804, N805 |
5 |
self must be supertype of its class |
reportGeneralTypeIssues |
issue | invalid-annotation |
| implicit string concatenation | reportImplicitStringConcatenation |
ISC001 |
5 |
| unhashable | reportUnhashable |
issue | issue |
| source code in stub file | reportInvalidStubStatement |
PYI010, PYI015 |
5 |
| incomplete stub | reportIncompleteStub |
issue | 5 |
invalid name in __all__ |
reportUnsupportedDunderAll |
F822 |
bad-dunder-all |
unresolvable __all__ |
reportUnsupportedDunderAll |
PLE0605 |
unresolvable-dunder-all |
| unused call result | reportUnusedCallResult |
issue | unused-call-result |
| unused coroutine | reportUnusedCoroutine |
issue | unused-coroutine |
unreachable except statement |
reportUnusedExcept |
issue | issue |
| unused expression | reportUnusedExpression |
B018 |
5 |
| unused ignore comment | reportUnnecessaryTypeIgnoreComment |
unused-ignore-comment, ignore-comment-unknown-rule |
unused-ignore |
| ignore comment without code | reportIgnoreCommentWithoutRule |
issue | issue |
| invalid ignore comment | reportTypeCommentUsage7 |
invalid-ignore-comment |
issue |
non-exhaustive match statement |
reportMatchNotExhaustive |
issue | non-exhaustive-match |
| too many positional patterns in match | reportGeneralTypeIssues |
invalid-match-pattern |
bad-match |
| unreachable code | reportUnreachable |
issue | unreachable6, unreachable-match-case |
| implicit override | reportImplicitOverride |
missing-override-decorator |
missing-override-decorator |
implicit Any expression |
reportAny |
issue | issue |
implicit Any attribute declaration |
reportUnannotatedClassAttribute |
issue | implicit-any-attribute |
explicit Any |
reportExplicitAny |
TID2512 |
explicit-any |
| implicit relative import | reportImplicitRelativeImport |
unresolved-import |
missing-import |
| non-overlapping cast | reportInvalidCast |
issue | issue |
| unsafe multiple inheritance | reportUnsafeMultipleInheritance |
issue | issue |
| unused parameter | reportUnusedParameter |
ARG001 |
hint5 |
| implicitly abstract class | reportImplicitAbstractClass |
issue | implicit-abstract-class |
| abstract class with no abstract methods | reportEmptyAbstractUsage |
issue | bad-instantiation |
| incompatible unannotated override | reportIncompatibleUnannotatedOverride, reportUnannotatedClassAttribute |
issue | bad-override-mutable-attribute |
| abstract method on non-abstract class | reportInvalidAbstractMethod |
issue | invalid-abstract-method |
self or cls with default value |
reportSelfClsDefault |
issue | bad-function-definition |
abstract method in @final class |
reportGeneralTypeIssues |
abstract-method-in-final-class |
bad-class-definition |
override @final method |
reportIncompatibleMethodOverride |
override-of-final-method |
bad-override |
subtype @final class |
reportGeneralTypeIssues |
subclass-of-final-class |
invalid-inheritance |
override Final attribute |
reportGeneralTypeIssues |
override-of-final-variable |
bad-override |
| unannotated protocol attribute | reportUnannotatedClassAttribute10 |
ambiguous-protocol-member |
unannotated-protocol-member |
object used in condition when __bool__ = None |
reportOperatorIssue |
unsupported-bool-conversion, unsupported-operator |
invalid-argument, not-callable, invalid-argument |
| conflicting metaclass | reportGeneralTypeIssues |
conflicting-metaclass |
invalid-inheritance |
cyclic class definition in .pyi file |
reportGeneralTypeIssues |
cyclic-class-definition |
invalid-inheritance |
| cyclic type alias | reportGeneralTypeIssues |
cyclic-type-alias-definition |
invalid-type-alias |
| dataclass default field order | reportGeneralTypeIssues |
dataclass-field-order |
bad-class-definition |
| duplicate base class | reportGeneralTypeIssues |
duplicate-base |
invalid-inheritance |
| syntax error in quoted type | no code | invalid-syntax-in-forward-annotation, escape-character-in-forward-annotation |
not-a-type |
@final on non-method |
reportGeneralTypeIssues |
final-on-non-method |
invalid-decorator |
| implicit string concatenation in quoted type | reportGeneralTypeIssues,reportImplicitStringConcatenation |
implicit-concatenated-string-type-annotation |
not-a-type |
| inconsistent MRO | reportGeneralTypeIssues |
inconsistent-mro |
invalid-inheritance |
| not awaitable | reportGeneralTypeIssues |
invalid-await |
not-async |
assign to ClassVar from instance |
reportAttributeAccessIssue |
invalid-attribute-access |
read-only |
ClassVar and Final |
reportInvalidTypeForm, reportAssignmentType |
redundant-final-classvar |
invalid-annotation |
assign to readonly @property |
reportAttributeAccessIssue |
invalid-assignment |
read-only |
| invalid base class | reportGeneralTypeIssues |
invalid-base |
invalid-inheritance |
| type annotation on enum member | reportGeneralTypeIssues |
invalid-enum-member-annotation |
invalid-annotation |
invalid except type |
reportGeneralTypeIssues |
invalid-exception-caught |
not-a-type |
invalid raise/from type |
reportGeneralTypeIssues |
invalid-raise |
bad-raise |
@override without overriding anything |
reportGeneralTypeIssues |
invalid-explicit-override |
bad-override |
| frozen/non-frozen dataclass inheritance | reportGeneralTypeIssues |
invalid-frozen-dataclass-subclass |
invalid-inheritance |
| class with both old & new generic syntax | reportGeneralTypeIssues |
invalid-generic-class |
invalid-type-var |
TypeVar with default before one without |
reportGeneralTypeIssues |
invalid-generic-class |
invalid-type-var |
invalid key in TypedDict index access |
reportGeneralTypeIssues |
invalid-key |
bad-typed-dict-key |
invalid key when instantiating TypedDict |
reportAssignmentType, reportCallIssue |
invalid-key |
bad-typed-dict-key, unexpected-keyword |
missing key when instantiating TypedDict |
reportAssignmentType, reportCallIssue |
missing-typed-dict-key |
bad-typed-dict-key,no-matching-overload |
| legacy positional arg after normal arg | reportGeneralTypeIssues |
invalid-legacy-positional-parameter |
bad-function-definition |
| invalid match pattern | reportGeneralTypeIssues |
invalid-match-pattern |
invalid-pattern |
NamedTuple multiple inheritance |
reportGeneralTypeIssues |
invalid-named-tuple |
invalid-inheritance |
NamedTuple attribute starting with _ |
reportGeneralTypeIssues |
invalid-named-tuple |
bad-class-definition |
override NamedTuple attribute |
reportIncompatibleVariableOverride |
invalid-named-tuple-override |
bad-override |
NewType first arg must be LiteralString |
reportArgumentType |
invalid-newtype |
invalid-argument |
NewType invalid base |
reportGeneralTypeIssues |
invalid-newtype |
invalid-argument |
NewType wrong name |
reportGeneralTypeIssues |
mismatched-type-name |
invalid-argument |
invalid legacy ParamSpec |
reportGeneralTypeIssues, reportCallIssue |
invalid-paramspec |
invalid-param-spec |
legacy ParamSpec wrong name |
reportGeneralTypeIssues |
mismatched-type-name |
invalid-param-spec |
Protocol inheriting from non-Protocol |
reportGeneralTypeIssues |
invalid-protocol |
invalid-inheritance |
invalid @total_ordering |
reportGeneralTypeIssues |
invalid-total-ordering |
missing-attribute |
invalid TypeAliasType |
reportGeneralTypeIssues |
invalid-type-alias-type |
invalid-type-alias |
invalid TypeGuard/TypeIs definition |
reportGeneralTypeIssues |
invalid-type-guard-definition |
bad-function-definition |
TypedDict with metaclass |
reportGeneralTypeIssues |
invalid-typed-dict-header |
invalid-inheritance |
TypedDict with invalid class argument |
reportGeneralTypeIssues |
unknown-argument |
bad-typed-dict |
TypedDict with method |
reportGeneralTypeIssues |
invalid-typed-dict-statement |
bad-class-definition |
legacy TypedDict wrong name |
reportGeneralTypeIssues |
mismatched-type-name |
name-mismatch |
isinstance on TypedDict |
reportArgumentType, reportGeneralTypeIssues |
isinstance-against-typed-dict |
invalid-argument, invalid-pattern |
isinstance on non-@runtime_checkable Protocol |
reportArgumentType |
isinstance-against-protocol |
invalid-argument, invalid-pattern |
unsafe @runtime_checkable isinstance call |
reportGeneralTypeIssues |
issue | unsafe-overlap |
non-callable __init_subclass__ |
reportAssignmentType |
non-callable-init-subclass |
issue |
| implicitly imported submodule | reportAttributeAccessIssue |
possibly-missing-submodule |
implicit-import |
| type annotation on subscript assignment | reportInvalidTypeForm |
invalid-type-form |
invalid-syntax |
| r-string quoted type | reportGeneralTypeIssues |
raw-string-type-annotation |
invalid-annotation |
| protocol attribute not defined on the class | reportGeneralTypeIssues |
ambiguous-protocol-member |
|
reveal_type info message |
no code | revealed-type |
reveal-type |
unsupported del |
reportGeneralTypeIssues |
invalid-syntax |
unsupported-delete, parse-error |
| invalid sentinel | reportArgumentType, reportCallIssue |
issue | invalid-sentinel12 |
| type var with type var in bound | reportGeneralTypeIssues |
invalid-type-variable-bound |
invalid-annotation |
| type var with type var in constraints | reportGeneralTypeIssues |
invalid-type-variable-constraints |
invalid-annotation |
| invalid type var default | reportGeneralTypeIssues |
invalid-type-variable-default |
invalid-type-var |
| shadowed type var | reportGeneralTypeIssues |
shadowed-type-variable |
invalid-type-var |
| unbound type var | reportGeneralTypeIssues |
unbound-type-variable |
invalid-type-var |
| type var tuple must be unpacked | reportGeneralTypeIssues |
issue | invalid-type-var-tuple |
legacy TypeVar wrong name |
reportGeneralTypeIssues |
mismatched-type-name |
invalid-type-var |
legacy TypeVar with one constraint |
reportGeneralTypeIssues |
invalid-legacy-type-variable |
invalid-type-var |
legacy TypeVar used with wrong variance |
reportGeneralTypeIssues |
issue | invalid-variance |
legacy TypeVar can be covariant/contravariant |
reportInvalidTypeVarUse |
issue | variance-mismatch |
legacy TypeVar redefinition |
invalid-legacy-type-variable |
13 | |
legacy TypeVar not assigned to variable |
invalid-legacy-type-variable |
invalid-type-var |
|
legacy namedtuple wrong name |
mismatched-type-name |
name-mismatch |
|
invalid TYPE_CHECKING assignment |
invalid-type-checking-constant |
invalid-type-checking-constant |
|
generic Enum |
invalid-generic-enum |
invalid-inheritance |
|
invalid use of @dataclass |
invalid-dataclass |
bad-class-definition |
|
| invalid override on frozen dataclass | invalid-dataclass-override |
bad-class-definition |
|
| assign to instance variable from class | invalid-attribute-access11 |
issue | |
| instance layout conflict | instance-layout-conflict |
invalid-inheritance |
|
non-decorator usage of final |
ineffective-final |
issue | |
| empty function body | empty-body |
empty-body |
|
| call "top" callable type | call-top-callable |
issue | |
| division by zero | division-by-zero |
division-by-zero |
|
duplicate KW_ONLY |
duplicate-kw-only |
issue | |
| invalid metaclass | invalid-metaclass |
invalid-inheritance |
|
TypedDict unpacked class arguments |
invalid-typed-dict-header |
invalid-inheritance |
|
| conditionally defined member | possibly-missing-attribute,possibly-missing-implicit-call |
issue | |
| conditionally defined import | issue | possibly-missing-import |
issue |
static_assert error |
static-assert-error |
issue | |
subclass dataclass with order=True |
subclass-of-dataclass-with-order |
issue | |
super call in NamedTuple |
super-call-in-named-tuple-method |
invalid-super-call |
|
reveal_type used without importing it |
undefined-reveal |
unimported-directive |
|
global with no declaration |
unresolved-global |
unknown-name |
|
| dynamic base class | unsupported-dynamic-base |
issue | |
| useless overload body | useless-overload-body |
useless-overload-body |
|
| zero step in slice | zero-stepsize-in-slice |
bad-index |
|
implicit Any from empty container |
issue | implicit-any-empty-container |
|
| inconsistent overload default parameter | issue | inconsistent-overload-default |
|
invalid Self type |
issue | invalid-self-type |
|
| dvergent type | issue | non-convergent-recursion |
|
unpack open TypedDict |
issue | open-unpacking |
|
| pytorch lints8 | pytorch-efficiency-lint-cuda-call, pytorch-efficiency-lint-item-call, pytorch-efficiency-lint-print-tensor, pytorch-efficiency-lint-redundant-to-call |
||
str as Iterable[str] or Sequence[str] |
issue | string-as-iterable |
|
| function without return type annotation | issue | ANN201 |
unannotated-return |
| useless builtin type conversion | issue | unnecessary-type-conversion |
-
Some checks are not present in ty, but are covered by ruff. It's safe to assume that astral won't duplicate functionality they already have in their linter, so we combine the two tools in this table. to avoid ambiguity, we reference the cryptic code when referring to ruff rules rather than their human readable name. ↩
-
Requires config to explicitly ban
Any↩ -
This rule barely works, see https://github.com/astral-sh/ty/issues/2158 ↩
-
This rule is half broken, see https://github.com/facebook/pyrefly/issues/3660 ↩
-
Lint rule covered by ruff, not in scope for a type checker ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩
-
This rule is mostly broken, see https://github.com/facebook/pyrefly/issues/3689 ↩
-
Does not detect invalid
# pyright:comments, only# type:ones ↩ -
These are lint rules specific to a 3rd party library which are out of scope for a type checker, so i'm not going to bother with these ↩
-
Doesn't catch everything, see https://github.com/facebook/pyrefly/issues/3690 ↩↩
-
Not the intended use case for this rule, it reports all unannotated class attributes not just
Protocols ↩ -
doesn't currently report mismatched sentinel name, see https://github.com/facebook/pyrefly/issues/4142#issuecomment-5087594256 ↩
-
see https://github.com/facebook/pyrefly/issues/3754#issuecomment-4678649318 ↩
-
doesn't catch most cases, see https://github.com/facebook/pyrefly/issues/3661#issuecomment-5099332062 ↩
-
see https://github.com/facebook/pyrefly/issues/3661#issuecomment-5098798075 ↩