python / python/mypy

report warn-redundant-annotation (similar to warn-redundant-cast)

Offen
#18,540 4 Kommentare 10 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

feature
Vorherrschende Sprache
Python
Sterne
20.6k
Forks
3.3k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

Feature

I frequently see people new to python typing over typing everything -- think x: int = function_that_obviously_returns_int(). I would like this to be an optional error

Pitch

in most cases it's somewhat harmless -- it adds a little bit of extra reading and occasionally a slight amount of runtime overhead. but in some cases it makes refactoring and typing a burdensome task (especially if the manual annotation was wrong or subtly wrong, or slightly incorrect, or correct at the time but inconsistent after a refactor).

I would like to suggest a new feature which allows mypy to report this as an optional diagnostic when someone adds an inline annotation which is unnecessary (when mypy already knows the rvalue's type given its expression).


I initially attempted to write something like this as a mypy plugin but I don't think the plugin interface actually gives enough interface points to make this diagnostic possible so I instead looked at how much work it would be to implement this in mypy directly. at a first pass it seems to be not that difficult!

diff --git a/mypy/checker.py b/mypy/checker.py
index 3d0f40283..9229c197c 100644
--- a/mypy/checker.py
+++ b/mypy/checker.py
@@ -2980,6 +2980,9 @@ class TypeChecker(NodeVisitor[None], CheckerPluginInterface):
         Handle all kinds of assignment statements (simple, indexed, multiple).
         """
 
+        if self.expr_checker.accept(s.rvalue) == s.type:
+            self.msg.redundant_annotation(s.type, s.rvalue)
+
         # Avoid type checking type aliases in stubs to avoid false
         # positives about modern type syntax available in stubs such
         # as X | Y.
diff --git a/mypy/errorcodes.py b/mypy/errorcodes.py
index 8f650aa30..5eeb7139c 100644
--- a/mypy/errorcodes.py
+++ b/mypy/errorcodes.py
@@ -164,6 +164,9 @@ NO_UNTYPED_CALL: Final = ErrorCode(
     "Disallow calling functions without type annotations from annotated functions",
     "General",
 )
+REDUNDANT_ANNOTATION: Final = ErrorCode(
+    "redundant-annotation", "Check that the annotation is necessary or can be omitted", "General"
+)
 REDUNDANT_CAST: Final = ErrorCode(
     "redundant-cast", "Check that cast changes type of expression", "General"
 )
diff --git a/mypy/messages.py b/mypy/messages.py
index b63310825..8e9648ed0 100644
--- a/mypy/messages.py
+++ b/mypy/messages.py
@@ -1768,6 +1768,13 @@ class MessageBuilder:
             f'Cannot instantiate type "Type[{format_type_bare(item, self.options)}]"', context
         )
 
+    def redundant_annotation(self, typ: Type, context: Context) -> None:
+        self.fail(
+            f"Annotation {format_type(typ, self.options)} is redundant (inferred type is the same)",
+            context,
+            code=codes.REDUNDANT_ANNOTATION,
+        )
+
     def redundant_cast(self, typ: Type, context: Context) -> None:
         self.fail(
             f"Redundant cast to {format_type(typ, self.options)}",

with an example file like this:

def f() -> int: ...

def g():
   x: int = f()  # stop doing this please!
   ...

my hacked version of mypy produces the desired diagnostic (though I didn't do the part where it's disabled by default and opted into but I just wanted to show a proof of concept!):

$ rm -rf .mypy_cache/ && mypy t.py --show-traceback
t.py:13: error: Annotation "int" is redundant (inferred type is the same)  [redundant-annotation]
Found 1 error in 1 file (checked 1 source file)

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne in mypy/checker.py bei TypeChecker.visit_assignment_stmt und lies dann mypy/errorcodes.py und mypy/messages.py zusammen mit dem vorgeschlagenen Diff. Verwende die Beispieldatei mit f() und g() als erste Reproduktion. Fertig ist die Aufgabe, wenn mypy unnötige Inline-Annotationen über eine optionale Diagnose melden kann, die standardmäßig deaktiviert bleibt.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
compilers
Issue-Typ
Feature
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
30/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.