Fred Tingaud 16f6c0aecf
Inline adoc when include has no additional value (#1940)
Inline adoc files when they are included exactly once.

Also fix language tags because this inlining gives us better information
on what language the code is written in.
2023-05-25 14:18:12 +02:00

78 lines
3.3 KiB
Plaintext

== Why is this an issue?
Checking that variable X has type T with https://docs.python.org/3/library/typing.html[type annotations] implies that X's value is of type T or a subtype of T. After such a check, it is a good practice to limit actions on X to those allowed by type T, even if a subclass of T allows different actions. Doing otherwise will confuse your fellow developers.
Just to be clear, it is common in python to perform an action without checking first if it is possible (see https://docs.python.org/3/glossary.html#term-eafp["Easier to ask for forgiveness than permission."]). However when type checks are performed, they should not contradict the following actions.
This rule raises an issue when an action performed on a variable might be possible, but it contradicts a previous type check. The list of checked actions corresponds to rules S2159, S3403, S5607, S5756, S5644, S3862, S5797, S5795 and S5632. These other rules only detect cases where the type of a variable is certain, i.e. it cannot be a subclass.
=== Noncompliant code example
[source,python]
----
def add_the_answer(param: str):
return param + 42 # Noncompliant. Fix this "+" operation; Type annotation on "param" suggest that operands have incompatible types.
# Note: In practice it is possible to create a class inheriting from both "str" and "int", but this would be a very confusing design.
----
=== Compliant solution
[source,python]
----
def add_the_answer(param: str):
return param + "42"
----
== Resources
* https://docs.python.org/3/library/functions.html#isinstance[Python documentation - ``++isinstance++`` function]
* https://docs.python.org/3/glossary.html#term-eafp[Python glossary - "Easier to ask for forgiveness than permission."]
ifdef::env-github,rspecator-view[]
'''
== Implementation Specification
(visible only on this page)
=== Highlighting
Secondary is always:
* message: "Inconsistent type check."
* location: the last type check giving us information on the variables' type. Ex: an isinstance call.
Primary varies depending on the issue:
* s2159 - Equality between incompatible types:
** message: Fix this equality check; Previous type checks suggest that operands have incompatible types.
* s3403 - identity check between incompatible types
** message: Fix this "is" check; Previous type checks suggest that operands have incompatible types.
* s5607 - operations on incompatible types
** message: Fix this "+" operation; Previous type checks suggest that operands have incompatible types.
* s5756 - calling a non-callable type
** message: Fix this call; Previous type checks suggest that "param" is not callable.
* s5644 - calling ``++__getitem__++`` on type which doesn't have this method
** message: Fix this __getitem__ operation; Previous type checks suggest that "param" does not have this method.
* s3862 - iteration operation on a non-iterable type
** message: Fix this unpacking; Previous type checks suggest that "param" is not iterable.
* s5795 - identity check relies on interpreter's cache
** message: Fix this condition; Previous type checks suggest that it relies on interpreter's cache.
* s5632 - ``++raise++`` used with a non-exception type
** message: Fix this "raise" statement; Previous type checks suggest that "param" is not an exception.
endif::env-github,rspecator-view[]