From 3f2ccf41016307dd25190bd60808ced860614ba6 Mon Sep 17 00:00:00 2001 From: LordBaryhobal Date: Thu, 9 Jul 2026 19:05:04 +0200 Subject: [PATCH] tests: add test covering some function subtyping rules --- tests/cases/checker/11_function_subtyping.py | 44 +++ .../checker/11_function_subtyping.py.ref.json | 282 ++++++++++++++++++ tests/checker.py | 3 + 3 files changed, 329 insertions(+) create mode 100644 tests/cases/checker/11_function_subtyping.py create mode 100644 tests/cases/checker/11_function_subtyping.py.ref.json diff --git a/tests/cases/checker/11_function_subtyping.py b/tests/cases/checker/11_function_subtyping.py new file mode 100644 index 0000000..86119c9 --- /dev/null +++ b/tests/cases/checker/11_function_subtyping.py @@ -0,0 +1,44 @@ +def a1(param: int) -> float: ... +def a2(param: float) -> int: ... + + +a = a1 +a = a2 + + +def b1(a: int, /) -> float: ... +def b2(b: float, /) -> int: ... + + +b = b1 +b = b2 + + +def c1(a: int) -> None: ... +def c2(p: float = 0, /, *, a: float = 0) -> None: ... + + +c = c1 +c = c2 + +# Invalid subtypes + + +def d1(a: int) -> float: ... +def d2(a: str) -> float: ... +def d3(a: int) -> str: ... + + +d = d1 +d = d2 +d = d3 + + +def e1(*, a: int = 0) -> None: ... +def e2(*, a: int) -> None: ... +def e3(*, a: int = 0, b: int) -> None: ... + + +e = e1 +e = e2 +e = e3 diff --git a/tests/cases/checker/11_function_subtyping.py.ref.json b/tests/cases/checker/11_function_subtyping.py.ref.json new file mode 100644 index 0000000..b39b2a8 --- /dev/null +++ b/tests/cases/checker/11_function_subtyping.py.ref.json @@ -0,0 +1,282 @@ +{ + "diagnostics": [ + { + "type": "Warning", + "location": { + "start": [ + 1, + 29 + ], + "end": [ + 1, + 32 + ] + }, + "message": "Unknown literal LiteralExpr(location=Location(lineno=1, col_offset=29, end_lineno=1, end_col_offset=32), value=Ellipsis)" + }, + { + "type": "Error", + "location": { + "start": [ + 1, + 22 + ], + "end": [ + 1, + 27 + ] + }, + "message": "Return type mismatch, annotated float but returns None" + }, + { + "type": "Warning", + "location": { + "start": [ + 2, + 29 + ], + "end": [ + 2, + 32 + ] + }, + "message": "Unknown literal LiteralExpr(location=Location(lineno=2, col_offset=29, end_lineno=2, end_col_offset=32), value=Ellipsis)" + }, + { + "type": "Error", + "location": { + "start": [ + 2, + 24 + ], + "end": [ + 2, + 27 + ] + }, + "message": "Return type mismatch, annotated int but returns None" + }, + { + "type": "Warning", + "location": { + "start": [ + 9, + 28 + ], + "end": [ + 9, + 31 + ] + }, + "message": "Unknown literal LiteralExpr(location=Location(lineno=9, col_offset=28, end_lineno=9, end_col_offset=31), value=Ellipsis)" + }, + { + "type": "Error", + "location": { + "start": [ + 9, + 21 + ], + "end": [ + 9, + 26 + ] + }, + "message": "Return type mismatch, annotated float but returns None" + }, + { + "type": "Warning", + "location": { + "start": [ + 10, + 28 + ], + "end": [ + 10, + 31 + ] + }, + "message": "Unknown literal LiteralExpr(location=Location(lineno=10, col_offset=28, end_lineno=10, end_col_offset=31), value=Ellipsis)" + }, + { + "type": "Error", + "location": { + "start": [ + 10, + 23 + ], + "end": [ + 10, + 26 + ] + }, + "message": "Return type mismatch, annotated int but returns None" + } + ], + "judgments": [ + { + "location": { + "from": "L1:29", + "to": "L1:32" + }, + "expr": { + "_type": "LiteralExpr", + "value": "..." + }, + "type": {} + }, + { + "location": { + "from": "L2:29", + "to": "L2:32" + }, + "expr": { + "_type": "LiteralExpr", + "value": "..." + }, + "type": {} + }, + { + "location": { + "from": "L5:4", + "to": "L5:6" + }, + "expr": { + "_type": "VariableExpr", + "name": "a1" + }, + "type": { + "params": { + "pos": [], + "mixed": [ + { + "pos": 0, + "name": "param", + "type": { + "name": "int" + }, + "required": true, + "unsupported": false + } + ], + "kw": [] + }, + "returns": { + "name": "float" + } + } + }, + { + "location": { + "from": "L6:4", + "to": "L6:6" + }, + "expr": { + "_type": "VariableExpr", + "name": "a2" + }, + "type": { + "params": { + "pos": [], + "mixed": [ + { + "pos": 0, + "name": "param", + "type": { + "name": "float" + }, + "required": true, + "unsupported": false + } + ], + "kw": [] + }, + "returns": { + "name": "int" + } + } + }, + { + "location": { + "from": "L9:28", + "to": "L9:31" + }, + "expr": { + "_type": "LiteralExpr", + "value": "..." + }, + "type": {} + }, + { + "location": { + "from": "L10:28", + "to": "L10:31" + }, + "expr": { + "_type": "LiteralExpr", + "value": "..." + }, + "type": {} + }, + { + "location": { + "from": "L13:4", + "to": "L13:6" + }, + "expr": { + "_type": "VariableExpr", + "name": "b1" + }, + "type": { + "params": { + "pos": [ + { + "pos": 0, + "name": "a", + "type": { + "name": "int" + }, + "required": true, + "unsupported": false + } + ], + "mixed": [], + "kw": [] + }, + "returns": { + "name": "float" + } + } + }, + { + "location": { + "from": "L14:4", + "to": "L14:6" + }, + "expr": { + "_type": "VariableExpr", + "name": "b2" + }, + "type": { + "params": { + "pos": [ + { + "pos": 0, + "name": "b", + "type": { + "name": "float" + }, + "required": true, + "unsupported": false + } + ], + "mixed": [], + "kw": [] + }, + "returns": { + "name": "int" + } + } + } + ] +} \ No newline at end of file diff --git a/tests/checker.py b/tests/checker.py index 2b591e7..7a630c5 100644 --- a/tests/checker.py +++ b/tests/checker.py @@ -18,6 +18,9 @@ class CustomEncoder(json.JSONEncoder): return ast.dump(o) if isinstance(o, TokenType): return o.name + if o == ...: + return "..." + return super().default(o)