From 6135d6a39b84c25d3f530250fff7cd937c63b57c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Miedzi=C5=84ski?= Date: Thu, 25 May 2017 00:13:27 +0200 Subject: [PATCH 1/3] Fix None slice bounds with strict-optional --- mypy/checkexpr.py | 3 ++- test-data/unit/check-expressions.test | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index b19a0a1bcfd2..660d3ef37313 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1893,10 +1893,11 @@ def analyze_super(self, e: SuperExpr, is_lvalue: bool) -> Type: return AnyType() def visit_slice_expr(self, e: SliceExpr) -> Type: + expected = UnionType.make_union([NoneTyp(), self.named_type('builtins.int')]) for index in [e.begin_index, e.end_index, e.stride]: if index: t = self.accept(index) - self.chk.check_subtype(t, self.named_type('builtins.int'), + self.chk.check_subtype(t, expected, index, messages.INVALID_SLICE_INDEX) return self.named_type('builtins.slice') diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test index 1d840269da42..167c7c9249ba 100644 --- a/test-data/unit/check-expressions.test +++ b/test-data/unit/check-expressions.test @@ -998,6 +998,7 @@ a[:o] # E: Slice index must be an integer or None [builtins fixtures/slice.pyi] [case testNoneSliceBounds] +# flags: --strict-optional from typing import Any a = None # type: Any a[None:1] From a31b666304ddd4fd7fd4f2fc3068f7383b395df0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Miedzi=C5=84ski?= Date: Thu, 25 May 2017 00:18:15 +0200 Subject: [PATCH 2/3] Add new strict-optional test --- test-data/unit/check-expressions.test | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test index 167c7c9249ba..ae1498acdadd 100644 --- a/test-data/unit/check-expressions.test +++ b/test-data/unit/check-expressions.test @@ -998,6 +998,15 @@ a[:o] # E: Slice index must be an integer or None [builtins fixtures/slice.pyi] [case testNoneSliceBounds] +from typing import Any +a = None # type: Any +a[None:1] +a[1:None] +a[None:] +a[:None] +[builtins fixtures/slice.pyi] + +[case testNoneSliceBoundsWithStrictOptional] # flags: --strict-optional from typing import Any a = None # type: Any From ffe0c361f0d233f5c43962f6103fd6d7a5abe87a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Miedzi=C5=84ski?= Date: Thu, 25 May 2017 16:14:27 +0200 Subject: [PATCH 3/3] Use typeanal.make_optional_type --- mypy/checkexpr.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 660d3ef37313..4f9b23da31ee 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -44,6 +44,7 @@ from mypy.util import split_module_names from mypy.typevars import fill_typevars from mypy.visitor import ExpressionVisitor +from mypy.typeanal import make_optional_type from mypy import experiments @@ -1893,7 +1894,7 @@ def analyze_super(self, e: SuperExpr, is_lvalue: bool) -> Type: return AnyType() def visit_slice_expr(self, e: SliceExpr) -> Type: - expected = UnionType.make_union([NoneTyp(), self.named_type('builtins.int')]) + expected = make_optional_type(self.named_type('builtins.int')) for index in [e.begin_index, e.end_index, e.stride]: if index: t = self.accept(index)