diff --git a/conformance/README.md b/conformance/README.md index 0b60a9490..59f94ea10 100644 --- a/conformance/README.md +++ b/conformance/README.md @@ -63,6 +63,7 @@ Test cases support the following special comments for declaring where errors sho * `# E[tag]`, where `tag` is an arbitrary string: must appear multiple times in a file with the same tag. Exactly one line with this tag must raise an error. * `# E[tag+]`: like `# E[tag]`, but errors may be raised on multiple lines. +* `# E[tag!]`: like `# E[tag]`, but at least one line must not raise an error. Each comment may be followed by a colon plus an explanation of the error; the explanation is ignored by the scoring system. diff --git a/conformance/results/mypy/qualifiers_final_annotation.toml b/conformance/results/mypy/qualifiers_final_annotation.toml index 099d55b0c..52e3e2aa2 100644 --- a/conformance/results/mypy/qualifiers_final_annotation.toml +++ b/conformance/results/mypy/qualifiers_final_annotation.toml @@ -1,50 +1,57 @@ conformant = "Partial" notes = """ +Infers invalid `Literal` values from `float`. Does not treat use of `Final` name as if it was replaced by the literal in `NamedTuple` definition. Does not allow conditional assignment of `Final` instance variable in `__init__` method. Does not allow redefinition of private class variable that is marked `Final` in parent class. Does not report modification of local `Final` variable via `for` statement. """ output = """ -qualifiers_final_annotation.py:16: error: Type in Final[...] can only be omitted if there is an initializer [misc] -qualifiers_final_annotation.py:18: error: Final[...] takes at most one type argument [misc] -qualifiers_final_annotation.py:34: error: Type in Final[...] can only be omitted if there is an initializer [misc] -qualifiers_final_annotation.py:38: error: Final name must be initialized with a value [misc] -qualifiers_final_annotation.py:54: error: Cannot assign to final attribute "ID5" [misc] -qualifiers_final_annotation.py:59: error: Cannot assign to final attribute "ID6" [misc] -qualifiers_final_annotation.py:62: error: Can only declare a final attribute in class body or __init__ [misc] -qualifiers_final_annotation.py:63: error: Can only declare a final attribute in class body or __init__ [misc] -qualifiers_final_annotation.py:65: error: Cannot assign to final attribute "ID7" [misc] -qualifiers_final_annotation.py:67: error: Cannot assign to final attribute "ID7" [misc] -qualifiers_final_annotation.py:71: error: Cannot assign to final name "RATE" [misc] -qualifiers_final_annotation.py:81: error: Cannot assign to final attribute "DEFAULT_ID" [misc] -qualifiers_final_annotation.py:94: error: Cannot assign to final name "BORDER_WIDTH" [misc] -qualifiers_final_annotation.py:96: error: Cannot assign to final name "__private" [misc] -qualifiers_final_annotation.py:107: error: Final can be only used as an outermost qualifier in a variable annotation [valid-type] -qualifiers_final_annotation.py:108: error: Variable should not be annotated with both ClassVar and Final [misc] -qualifiers_final_annotation.py:118: error: Final can be only used as an outermost qualifier in a variable annotation [valid-type] -qualifiers_final_annotation.py:121: error: Final can be only used as an outermost qualifier in a variable annotation [valid-type] -qualifiers_final_annotation.py:131: error: Final[...] can't be used inside a TypedDict [valid-type] -qualifiers_final_annotation.py:136: error: Final[...] can't be used inside a NamedTuple [valid-type] -qualifiers_final_annotation.py:145: error: Invalid "NamedTuple()" field name [misc] -qualifiers_final_annotation.py:147: error: Unexpected keyword argument "x" for "N" [call-arg] -qualifiers_final_annotation.py:147: error: Unexpected keyword argument "y" for "N" [call-arg] -qualifiers_final_annotation.py:148: error: Unexpected keyword argument "a" for "N" [call-arg] -qualifiers_final_annotation.py:149: error: Unexpected keyword argument "x" for "N" [call-arg] -qualifiers_final_annotation.py:149: error: Unexpected keyword argument "y" for "N" [call-arg] -qualifiers_final_annotation.py:155: error: Cannot assign to final name "ID1" [misc] -qualifiers_final_annotation.py:159: error: Cannot assign to final name "x" [misc] -qualifiers_final_annotation.py:161: error: Cannot assign to final name "x" [misc] -qualifiers_final_annotation.py:166: error: Incompatible types in assignment (expression has type "TextIOWrapper[_WrappedBuffer]", variable has type "int") [assignment] -qualifiers_final_annotation.py:169: error: Cannot assign to final name "x" [misc] -qualifiers_final_annotation.py:180: error: Cannot assign to final name "TEN" [misc] -qualifiers_final_annotation.py:184: error: Cannot assign to final name "PI" [misc] +qualifiers_final_annotation.py:24: error: Expression is of type "Literal[3]", not "int" [assert-type] +qualifiers_final_annotation.py:29: error: Expression is of type "Literal[3.14]", not "float" [assert-type] +qualifiers_final_annotation.py:30: error: Expression is of type "Literal[3.14]", not "float | int" [assert-type] +qualifiers_final_annotation.py:37: error: Type in Final[...] can only be omitted if there is an initializer [misc] +qualifiers_final_annotation.py:39: error: Final[...] takes at most one type argument [misc] +qualifiers_final_annotation.py:55: error: Type in Final[...] can only be omitted if there is an initializer [misc] +qualifiers_final_annotation.py:59: error: Final name must be initialized with a value [misc] +qualifiers_final_annotation.py:75: error: Cannot assign to final attribute "ID5" [misc] +qualifiers_final_annotation.py:80: error: Cannot assign to final attribute "ID6" [misc] +qualifiers_final_annotation.py:83: error: Can only declare a final attribute in class body or __init__ [misc] +qualifiers_final_annotation.py:84: error: Can only declare a final attribute in class body or __init__ [misc] +qualifiers_final_annotation.py:86: error: Cannot assign to final attribute "ID7" [misc] +qualifiers_final_annotation.py:88: error: Cannot assign to final attribute "ID7" [misc] +qualifiers_final_annotation.py:92: error: Cannot assign to final name "RATE" [misc] +qualifiers_final_annotation.py:102: error: Cannot assign to final attribute "DEFAULT_ID" [misc] +qualifiers_final_annotation.py:115: error: Cannot assign to final name "BORDER_WIDTH" [misc] +qualifiers_final_annotation.py:117: error: Cannot assign to final name "__private" [misc] +qualifiers_final_annotation.py:128: error: Final can be only used as an outermost qualifier in a variable annotation [valid-type] +qualifiers_final_annotation.py:129: error: Variable should not be annotated with both ClassVar and Final [misc] +qualifiers_final_annotation.py:139: error: Final can be only used as an outermost qualifier in a variable annotation [valid-type] +qualifiers_final_annotation.py:142: error: Final can be only used as an outermost qualifier in a variable annotation [valid-type] +qualifiers_final_annotation.py:152: error: Final[...] can't be used inside a TypedDict [valid-type] +qualifiers_final_annotation.py:157: error: Final[...] can't be used inside a NamedTuple [valid-type] +qualifiers_final_annotation.py:166: error: Invalid "NamedTuple()" field name [misc] +qualifiers_final_annotation.py:168: error: Unexpected keyword argument "x" for "N" [call-arg] +qualifiers_final_annotation.py:168: error: Unexpected keyword argument "y" for "N" [call-arg] +qualifiers_final_annotation.py:169: error: Unexpected keyword argument "a" for "N" [call-arg] +qualifiers_final_annotation.py:170: error: Unexpected keyword argument "x" for "N" [call-arg] +qualifiers_final_annotation.py:170: error: Unexpected keyword argument "y" for "N" [call-arg] +qualifiers_final_annotation.py:178: error: Cannot assign to final name "ID1" [misc] +qualifiers_final_annotation.py:182: error: Cannot assign to final name "x" [misc] +qualifiers_final_annotation.py:184: error: Cannot assign to final name "x" [misc] +qualifiers_final_annotation.py:189: error: Incompatible types in assignment (expression has type "TextIOWrapper[_WrappedBuffer]", variable has type "int") [assignment] +qualifiers_final_annotation.py:192: error: Cannot assign to final name "x" [misc] +qualifiers_final_annotation.py:203: error: Cannot assign to final name "TEN" [misc] +qualifiers_final_annotation.py:207: error: Cannot assign to final name "PI" [misc] """ conformance_automated = "Fail" errors_diff = """ -Line 163: Expected 1 errors -Line 59: Unexpected errors ['qualifiers_final_annotation.py:59: error: Cannot assign to final attribute "ID6" [misc]'] -Line 96: Unexpected errors ['qualifiers_final_annotation.py:96: error: Cannot assign to final name "__private" [misc]'] -Line 145: Unexpected errors ['qualifiers_final_annotation.py:145: error: Invalid "NamedTuple()" field name [misc]'] -Line 147: Unexpected errors ['qualifiers_final_annotation.py:147: error: Unexpected keyword argument "x" for "N" [call-arg]', 'qualifiers_final_annotation.py:147: error: Unexpected keyword argument "y" for "N" [call-arg]'] +Line 186: Expected 1 errors +Lines 29, 30: Expected at least one success (tag 'bare3') +Line 29: Unexpected errors ['qualifiers_final_annotation.py:29: error: Expression is of type "Literal[3.14]", not "float" [assert-type]'] +Line 30: Unexpected errors ['qualifiers_final_annotation.py:30: error: Expression is of type "Literal[3.14]", not "float | int" [assert-type]'] +Line 80: Unexpected errors ['qualifiers_final_annotation.py:80: error: Cannot assign to final attribute "ID6" [misc]'] +Line 117: Unexpected errors ['qualifiers_final_annotation.py:117: error: Cannot assign to final name "__private" [misc]'] +Line 166: Unexpected errors ['qualifiers_final_annotation.py:166: error: Invalid "NamedTuple()" field name [misc]'] +Line 168: Unexpected errors ['qualifiers_final_annotation.py:168: error: Unexpected keyword argument "x" for "N" [call-arg]', 'qualifiers_final_annotation.py:168: error: Unexpected keyword argument "y" for "N" [call-arg]'] """ diff --git a/conformance/results/pycroscope/qualifiers_final_annotation.toml b/conformance/results/pycroscope/qualifiers_final_annotation.toml index 0784a273e..7be3a9c27 100644 --- a/conformance/results/pycroscope/qualifiers_final_annotation.toml +++ b/conformance/results/pycroscope/qualifiers_final_annotation.toml @@ -1,35 +1,47 @@ -conformance_automated = "Pass" +conformant = "Partial" +notes = """ +Infers invalid `Literal` values from `float` and `range`. +""" +conformance_automated = "Fail" errors_diff = """ +Lines 29, 30: Expected at least one success (tag 'bare3') +Line 29: Unexpected errors ['./qualifiers_final_annotation.py:29:12: Literal[3.14] is not equivalent to float | int'] +Line 30: Unexpected errors ['./qualifiers_final_annotation.py:30:12: Literal[3.14] is not equivalent to float | int'] +Line 33: Unexpected errors ['./qualifiers_final_annotation.py:33:12: Literal[range(0, 3)] is not equivalent to range'] """ output = """ -./qualifiers_final_annotation.py:16:6: Final annotation without assignment requires an explicit type [invalid_qualifier] -./qualifiers_final_annotation.py:18:6: Invalid type annotation (, ) [invalid_annotation] -./qualifiers_final_annotation.py:34:9: Final annotation without assignment requires an explicit type [invalid_qualifier] -./qualifiers_final_annotation.py:34:4: Final class attributes without initializers must be assigned in __init__ [invalid_qualifier] -./qualifiers_final_annotation.py:38:4: Final class attributes without initializers must be assigned in __init__ [invalid_qualifier] -./qualifiers_final_annotation.py:54:8: Cannot assign to final name ID5 [incompatible_assignment] -./qualifiers_final_annotation.py:62:18: Final instance attributes may be declared only in __init__ [invalid_qualifier] -./qualifiers_final_annotation.py:63:18: Final instance attributes may be declared only in __init__ [invalid_qualifier] -./qualifiers_final_annotation.py:65:8: Cannot assign to final name ID7 [incompatible_assignment] -./qualifiers_final_annotation.py:67:8: Cannot assign to final name ID7 [incompatible_assignment] -./qualifiers_final_annotation.py:71:0: Cannot assign to final name RATE [incompatible_assignment] -./qualifiers_final_annotation.py:81:0: Cannot assign to final name DEFAULT_ID [incompatible_assignment] -./qualifiers_final_annotation.py:94:4: Cannot override final attribute BORDER_WIDTH [incompatible_override] -./qualifiers_final_annotation.py:107:12: Final cannot be combined with ClassVar [invalid_qualifier] -./qualifiers_final_annotation.py:108:12: Final cannot be combined with ClassVar [invalid_qualifier] -./qualifiers_final_annotation.py:118:3: Unrecognized annotation typing.Final[] [invalid_annotation] -./qualifiers_final_annotation.py:121:13: Unexpected Final annotation [invalid_qualifier] -./qualifiers_final_annotation.py:131:7: Unexpected Final annotation [invalid_qualifier] -./qualifiers_final_annotation.py:136:4: Final class attributes without initializers must be assigned in __init__ [invalid_qualifier] -./qualifiers_final_annotation.py:148:0: In call to pycroscope.signature.N: Missing required argument 'x' [incompatible_call] -./qualifiers_final_annotation.py:149:4: Incompatible argument type for x: expected int but got Literal[''] [incompatible_argument] -./qualifiers_final_annotation.py:149:10: Incompatible argument type for y: expected int but got Literal[''] [incompatible_argument] -./qualifiers_final_annotation.py:155:4: Cannot assign to final name ID1 [incompatible_assignment] -./qualifiers_final_annotation.py:159:4: Cannot assign to final name x [incompatible_assignment] -./qualifiers_final_annotation.py:161:9: Cannot assign to final name x [incompatible_assignment] -./qualifiers_final_annotation.py:163:8: Cannot assign to final name x [incompatible_assignment] -./qualifiers_final_annotation.py:166:29: Cannot assign to final name x [incompatible_assignment] -./qualifiers_final_annotation.py:169:8: Cannot assign to final name x [incompatible_assignment] -./qualifiers_final_annotation.py:180:0: Cannot assign to final name TEN [incompatible_assignment] -./qualifiers_final_annotation.py:184:0: Cannot assign to final name PI [incompatible_assignment] +./qualifiers_final_annotation.py:24:12: Literal[3] is not equivalent to int +./qualifiers_final_annotation.py:29:12: Literal[3.14] is not equivalent to float | int +./qualifiers_final_annotation.py:30:12: Literal[3.14] is not equivalent to float | int +./qualifiers_final_annotation.py:33:12: Literal[range(0, 3)] is not equivalent to range +./qualifiers_final_annotation.py:37:6: Final annotation without assignment requires an explicit type [invalid_qualifier] +./qualifiers_final_annotation.py:39:6: Invalid type annotation (, ) [invalid_annotation] +./qualifiers_final_annotation.py:55:9: Final annotation without assignment requires an explicit type [invalid_qualifier] +./qualifiers_final_annotation.py:55:4: Final class attributes without initializers must be assigned in __init__ [invalid_qualifier] +./qualifiers_final_annotation.py:59:4: Final class attributes without initializers must be assigned in __init__ [invalid_qualifier] +./qualifiers_final_annotation.py:75:8: Cannot assign to final name ID5 [incompatible_assignment] +./qualifiers_final_annotation.py:83:18: Final instance attributes may be declared only in __init__ [invalid_qualifier] +./qualifiers_final_annotation.py:84:18: Final instance attributes may be declared only in __init__ [invalid_qualifier] +./qualifiers_final_annotation.py:86:8: Cannot assign to final name ID7 [incompatible_assignment] +./qualifiers_final_annotation.py:88:8: Cannot assign to final name ID7 [incompatible_assignment] +./qualifiers_final_annotation.py:92:0: Cannot assign to final name RATE [incompatible_assignment] +./qualifiers_final_annotation.py:102:0: Cannot assign to final name DEFAULT_ID [incompatible_assignment] +./qualifiers_final_annotation.py:115:4: Cannot override final attribute BORDER_WIDTH [incompatible_override] +./qualifiers_final_annotation.py:128:12: Final cannot be combined with ClassVar [invalid_qualifier] +./qualifiers_final_annotation.py:129:12: Final cannot be combined with ClassVar [invalid_qualifier] +./qualifiers_final_annotation.py:139:3: Unrecognized annotation typing.Final[] [invalid_annotation] +./qualifiers_final_annotation.py:142:13: Unexpected Final annotation [invalid_qualifier] +./qualifiers_final_annotation.py:152:7: Unexpected Final annotation [invalid_qualifier] +./qualifiers_final_annotation.py:157:4: Final class attributes without initializers must be assigned in __init__ [invalid_qualifier] +./qualifiers_final_annotation.py:169:0: In call to pycroscope.signature.N: Missing required argument 'x' [incompatible_call] +./qualifiers_final_annotation.py:170:4: Incompatible argument type for x: expected int but got Literal[''] [incompatible_argument] +./qualifiers_final_annotation.py:170:10: Incompatible argument type for y: expected int but got Literal[''] [incompatible_argument] +./qualifiers_final_annotation.py:178:4: Cannot assign to final name ID1 [incompatible_assignment] +./qualifiers_final_annotation.py:182:4: Cannot assign to final name x [incompatible_assignment] +./qualifiers_final_annotation.py:184:9: Cannot assign to final name x [incompatible_assignment] +./qualifiers_final_annotation.py:186:8: Cannot assign to final name x [incompatible_assignment] +./qualifiers_final_annotation.py:189:29: Cannot assign to final name x [incompatible_assignment] +./qualifiers_final_annotation.py:192:8: Cannot assign to final name x [incompatible_assignment] +./qualifiers_final_annotation.py:203:0: Cannot assign to final name TEN [incompatible_assignment] +./qualifiers_final_annotation.py:207:0: Cannot assign to final name PI [incompatible_assignment] """ diff --git a/conformance/results/pyrefly/qualifiers_final_annotation.toml b/conformance/results/pyrefly/qualifiers_final_annotation.toml index 4da0650c7..1d73df29d 100644 --- a/conformance/results/pyrefly/qualifiers_final_annotation.toml +++ b/conformance/results/pyrefly/qualifiers_final_annotation.toml @@ -2,36 +2,37 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ -ERROR qualifiers_final_annotation.py:16:7-12: Expected a type argument for `Final` [invalid-annotation] -ERROR qualifiers_final_annotation.py:18:7-22: Expected 1 type argument for `Final`, got 2 [invalid-annotation] -ERROR qualifiers_final_annotation.py:34:5-8: Final attribute declared in class body must be initialized with a value or in `__init__` [invalid-annotation] -ERROR qualifiers_final_annotation.py:38:5-8: Final attribute declared in class body must be initialized with a value or in `__init__` [invalid-annotation] -ERROR qualifiers_final_annotation.py:54:9-17: Cannot set field `ID5` [read-only] -ERROR qualifiers_final_annotation.py:62:9-17: Cannot set field `id3` [read-only] -ERROR qualifiers_final_annotation.py:63:9-17: Cannot set field `id4` [read-only] -ERROR qualifiers_final_annotation.py:65:9-17: Cannot set field `ID7` [read-only] -ERROR qualifiers_final_annotation.py:67:9-17: Cannot set field `ID7` [read-only] -ERROR qualifiers_final_annotation.py:71:8-11: Cannot assign to variable `RATE` because it is marked final [bad-assignment] -ERROR qualifiers_final_annotation.py:81:1-18: Cannot set field `DEFAULT_ID` [read-only] -ERROR qualifiers_final_annotation.py:94:5-17: `BORDER_WIDTH` is declared as final in parent class `ClassC` [bad-override] -ERROR qualifiers_final_annotation.py:107:5-11: `Final` may not be nested inside `ClassVar` [invalid-annotation] -ERROR qualifiers_final_annotation.py:108:19-27: `ClassVar` may not be nested inside `Final` [invalid-annotation] -ERROR qualifiers_final_annotation.py:118:9-19: `Final` is not allowed in this context [invalid-annotation] -ERROR qualifiers_final_annotation.py:121:14-19: `Final` is only allowed on a class or local variable annotation [invalid-annotation] -ERROR qualifiers_final_annotation.py:121:14-30: `Final` is not allowed in this context [invalid-annotation] -ERROR qualifiers_final_annotation.py:131:5-6: `Final` may not be used for TypedDict members [invalid-annotation] -ERROR qualifiers_final_annotation.py:136:5-6: `Final` may not be used for NamedTuple members [invalid-annotation] -ERROR qualifiers_final_annotation.py:148:2-7: Missing argument `x` in function `N.__new__` [missing-argument] -ERROR qualifiers_final_annotation.py:148:2-7: Missing argument `y` in function `N.__new__` [missing-argument] -ERROR qualifiers_final_annotation.py:148:3-4: Unexpected keyword argument `a` in function `N.__new__` [unexpected-keyword] -ERROR qualifiers_final_annotation.py:149:5-7: Argument `Literal['']` is not assignable to parameter `x` with type `int` in function `N.__new__` [bad-argument-type] -ERROR qualifiers_final_annotation.py:149:11-13: Argument `Literal['']` is not assignable to parameter `y` with type `int` in function `N.__new__` [bad-argument-type] -ERROR qualifiers_final_annotation.py:155:11-12: Cannot assign to variable `ID1` because it is marked final [bad-assignment] -ERROR qualifiers_final_annotation.py:159:5-11: Cannot assign to variable `x` because it is marked final [bad-assignment] -ERROR qualifiers_final_annotation.py:161:15-16: Cannot assign to variable `x` because it is marked final [bad-assignment] -ERROR qualifiers_final_annotation.py:163:14-23: Cannot assign to variable `x` because it is marked final [bad-assignment] -ERROR qualifiers_final_annotation.py:166:10-26: Cannot assign to variable `x` because it is marked final [bad-assignment] -ERROR qualifiers_final_annotation.py:169:5-11: Cannot assign to variable `x` because it is marked final [bad-assignment] -ERROR qualifiers_final_annotation.py:180:1-4: Cannot assign to `TEN` because it is imported as final [bad-assignment] -ERROR qualifiers_final_annotation.py:184:1-3: Cannot assign to `PI` because it is imported as final [bad-assignment] +ERROR qualifiers_final_annotation.py:23:12-31: assert_type(int, Literal[3]) failed [assert-type] +ERROR qualifiers_final_annotation.py:37:7-12: Expected a type argument for `Final` [invalid-annotation] +ERROR qualifiers_final_annotation.py:39:7-22: Expected 1 type argument for `Final`, got 2 [invalid-annotation] +ERROR qualifiers_final_annotation.py:55:5-8: Final attribute declared in class body must be initialized with a value or in `__init__` [invalid-annotation] +ERROR qualifiers_final_annotation.py:59:5-8: Final attribute declared in class body must be initialized with a value or in `__init__` [invalid-annotation] +ERROR qualifiers_final_annotation.py:75:9-17: Cannot set field `ID5` [read-only] +ERROR qualifiers_final_annotation.py:83:9-17: Cannot set field `id3` [read-only] +ERROR qualifiers_final_annotation.py:84:9-17: Cannot set field `id4` [read-only] +ERROR qualifiers_final_annotation.py:86:9-17: Cannot set field `ID7` [read-only] +ERROR qualifiers_final_annotation.py:88:9-17: Cannot set field `ID7` [read-only] +ERROR qualifiers_final_annotation.py:92:8-11: Cannot assign to variable `RATE` because it is marked final [bad-assignment] +ERROR qualifiers_final_annotation.py:102:1-18: Cannot set field `DEFAULT_ID` [read-only] +ERROR qualifiers_final_annotation.py:115:5-17: `BORDER_WIDTH` is declared as final in parent class `ClassC` [bad-override] +ERROR qualifiers_final_annotation.py:128:5-11: `Final` may not be nested inside `ClassVar` [invalid-annotation] +ERROR qualifiers_final_annotation.py:129:19-27: `ClassVar` may not be nested inside `Final` [invalid-annotation] +ERROR qualifiers_final_annotation.py:139:9-19: `Final` is not allowed in this context [invalid-annotation] +ERROR qualifiers_final_annotation.py:142:14-19: `Final` is only allowed on a class or local variable annotation [invalid-annotation] +ERROR qualifiers_final_annotation.py:142:14-30: `Final` is not allowed in this context [invalid-annotation] +ERROR qualifiers_final_annotation.py:152:5-6: `Final` may not be used for TypedDict members [invalid-annotation] +ERROR qualifiers_final_annotation.py:157:5-6: `Final` may not be used for NamedTuple members [invalid-annotation] +ERROR qualifiers_final_annotation.py:169:2-7: Missing argument `x` in function `N.__new__` [missing-argument] +ERROR qualifiers_final_annotation.py:169:2-7: Missing argument `y` in function `N.__new__` [missing-argument] +ERROR qualifiers_final_annotation.py:169:3-4: Unexpected keyword argument `a` in function `N.__new__` [unexpected-keyword] +ERROR qualifiers_final_annotation.py:170:5-7: Argument `Literal['']` is not assignable to parameter `x` with type `int` in function `N.__new__` [bad-argument-type] +ERROR qualifiers_final_annotation.py:170:11-13: Argument `Literal['']` is not assignable to parameter `y` with type `int` in function `N.__new__` [bad-argument-type] +ERROR qualifiers_final_annotation.py:178:11-12: Cannot assign to variable `ID1` because it is marked final [bad-assignment] +ERROR qualifiers_final_annotation.py:182:5-11: Cannot assign to variable `x` because it is marked final [bad-assignment] +ERROR qualifiers_final_annotation.py:184:15-16: Cannot assign to variable `x` because it is marked final [bad-assignment] +ERROR qualifiers_final_annotation.py:186:14-23: Cannot assign to variable `x` because it is marked final [bad-assignment] +ERROR qualifiers_final_annotation.py:189:10-26: Cannot assign to variable `x` because it is marked final [bad-assignment] +ERROR qualifiers_final_annotation.py:192:5-11: Cannot assign to variable `x` because it is marked final [bad-assignment] +ERROR qualifiers_final_annotation.py:203:1-4: Cannot assign to `TEN` because it is imported as final [bad-assignment] +ERROR qualifiers_final_annotation.py:207:1-3: Cannot assign to `PI` because it is imported as final [bad-assignment] """ diff --git a/conformance/results/pyright/qualifiers_final_annotation.toml b/conformance/results/pyright/qualifiers_final_annotation.toml index 0fb73bda6..7a44da79e 100644 --- a/conformance/results/pyright/qualifiers_final_annotation.toml +++ b/conformance/results/pyright/qualifiers_final_annotation.toml @@ -1,48 +1,50 @@ conformant = "Pass" output = """ -qualifiers_final_annotation.py:16:1 - error: "BAD1" is declared Final, but value is not assigned (reportGeneralTypeIssues) -qualifiers_final_annotation.py:18:7 - error: Expected a single type argument after "Final" (reportInvalidTypeForm) -qualifiers_final_annotation.py:34:5 - error: "ID2" is declared Final, but value is not assigned (reportGeneralTypeIssues) -qualifiers_final_annotation.py:38:5 - error: "ID3" is declared Final, but value is not assigned (reportGeneralTypeIssues) -qualifiers_final_annotation.py:54:14 - error: Cannot assign to attribute "ID5" for class "ClassA*" +qualifiers_final_annotation.py:24:13 - error: "assert_type" mismatch: expected "int" but received "Literal[3]" (reportAssertTypeFailure) +qualifiers_final_annotation.py:30:13 - error: "assert_type" mismatch: expected "float | int" but received "float" (reportAssertTypeFailure) +qualifiers_final_annotation.py:37:1 - error: "BAD1" is declared Final, but value is not assigned (reportGeneralTypeIssues) +qualifiers_final_annotation.py:39:7 - error: Expected a single type argument after "Final" (reportInvalidTypeForm) +qualifiers_final_annotation.py:55:5 - error: "ID2" is declared Final, but value is not assigned (reportGeneralTypeIssues) +qualifiers_final_annotation.py:59:5 - error: "ID3" is declared Final, but value is not assigned (reportGeneralTypeIssues) +qualifiers_final_annotation.py:75:14 - error: Cannot assign to attribute "ID5" for class "ClassA*"   Attribute "ID5" cannot be assigned through a class instance because it is a ClassVar   "ID5" is declared as Final and cannot be reassigned (reportAttributeAccessIssue) -qualifiers_final_annotation.py:62:19 - error: "Final" is not allowed in this context (reportInvalidTypeForm) -qualifiers_final_annotation.py:63:19 - error: "Final" is not allowed in this context (reportInvalidTypeForm) -qualifiers_final_annotation.py:63:32 - error: Cannot assign to attribute "id4" for class "ClassA*" +qualifiers_final_annotation.py:83:19 - error: "Final" is not allowed in this context (reportInvalidTypeForm) +qualifiers_final_annotation.py:84:19 - error: "Final" is not allowed in this context (reportInvalidTypeForm) +qualifiers_final_annotation.py:84:32 - error: Cannot assign to attribute "id4" for class "ClassA*"   "Literal[1]" is not assignable to "Final" (reportAttributeAccessIssue) -qualifiers_final_annotation.py:65:14 - error: Cannot assign to attribute "ID7" for class "ClassA*" +qualifiers_final_annotation.py:86:14 - error: Cannot assign to attribute "ID7" for class "ClassA*"   Attribute "ID7" cannot be assigned through a class instance because it is a ClassVar   "ID7" is declared as Final and cannot be reassigned (reportAttributeAccessIssue) -qualifiers_final_annotation.py:67:14 - error: Cannot assign to attribute "ID7" for class "ClassA*" +qualifiers_final_annotation.py:88:14 - error: Cannot assign to attribute "ID7" for class "ClassA*"   Attribute "ID7" cannot be assigned through a class instance because it is a ClassVar   "ID7" is declared as Final and cannot be reassigned (reportAttributeAccessIssue) -qualifiers_final_annotation.py:71:1 - error: "RATE" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) -qualifiers_final_annotation.py:81:8 - error: Cannot assign to attribute "DEFAULT_ID" for class "type[ClassB]" +qualifiers_final_annotation.py:92:1 - error: "RATE" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) +qualifiers_final_annotation.py:102:8 - error: Cannot assign to attribute "DEFAULT_ID" for class "type[ClassB]"   "DEFAULT_ID" is declared as Final and cannot be reassigned (reportAttributeAccessIssue) -qualifiers_final_annotation.py:94:5 - error: "BORDER_WIDTH" cannot be redeclared because parent class "ClassC" declares it as Final (reportGeneralTypeIssues) -qualifiers_final_annotation.py:107:22 - error: "Final" is not allowed in this context (reportInvalidTypeForm) -qualifiers_final_annotation.py:108:19 - error: "ClassVar" is not allowed in this context (reportInvalidTypeForm) -qualifiers_final_annotation.py:118:9 - error: "Final" is not allowed in this context (reportInvalidTypeForm) -qualifiers_final_annotation.py:121:14 - error: "Final" is not allowed in this context (reportInvalidTypeForm) -qualifiers_final_annotation.py:131:5 - error: "b" is declared Final, but value is not assigned (reportGeneralTypeIssues) -qualifiers_final_annotation.py:131:8 - error: "Final" is not allowed in this context (reportInvalidTypeForm) -qualifiers_final_annotation.py:136:5 - error: "b" is declared Final, but value is not assigned (reportGeneralTypeIssues) -qualifiers_final_annotation.py:136:8 - error: "Final" is not allowed in this context (reportInvalidTypeForm) -qualifiers_final_annotation.py:148:1 - error: Arguments missing for parameters "x", "y" (reportCallIssue) -qualifiers_final_annotation.py:148:3 - error: No parameter named "a" (reportCallIssue) -qualifiers_final_annotation.py:149:5 - error: Argument of type "Literal['']" cannot be assigned to parameter "x" of type "int" in function "__new__" +qualifiers_final_annotation.py:115:5 - error: "BORDER_WIDTH" cannot be redeclared because parent class "ClassC" declares it as Final (reportGeneralTypeIssues) +qualifiers_final_annotation.py:128:22 - error: "Final" is not allowed in this context (reportInvalidTypeForm) +qualifiers_final_annotation.py:129:19 - error: "ClassVar" is not allowed in this context (reportInvalidTypeForm) +qualifiers_final_annotation.py:139:9 - error: "Final" is not allowed in this context (reportInvalidTypeForm) +qualifiers_final_annotation.py:142:14 - error: "Final" is not allowed in this context (reportInvalidTypeForm) +qualifiers_final_annotation.py:152:5 - error: "b" is declared Final, but value is not assigned (reportGeneralTypeIssues) +qualifiers_final_annotation.py:152:8 - error: "Final" is not allowed in this context (reportInvalidTypeForm) +qualifiers_final_annotation.py:157:5 - error: "b" is declared Final, but value is not assigned (reportGeneralTypeIssues) +qualifiers_final_annotation.py:157:8 - error: "Final" is not allowed in this context (reportInvalidTypeForm) +qualifiers_final_annotation.py:169:1 - error: Arguments missing for parameters "x", "y" (reportCallIssue) +qualifiers_final_annotation.py:169:3 - error: No parameter named "a" (reportCallIssue) +qualifiers_final_annotation.py:170:5 - error: Argument of type "Literal['']" cannot be assigned to parameter "x" of type "int" in function "__new__"   "Literal['']" is not assignable to "int" (reportArgumentType) -qualifiers_final_annotation.py:149:11 - error: Argument of type "Literal['']" cannot be assigned to parameter "y" of type "int" in function "__new__" +qualifiers_final_annotation.py:170:11 - error: Argument of type "Literal['']" cannot be assigned to parameter "y" of type "int" in function "__new__"   "Literal['']" is not assignable to "int" (reportArgumentType) -qualifiers_final_annotation.py:155:5 - error: "ID1" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) -qualifiers_final_annotation.py:159:5 - error: "x" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) -qualifiers_final_annotation.py:161:10 - error: "x" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) -qualifiers_final_annotation.py:163:9 - error: "x" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) -qualifiers_final_annotation.py:166:30 - error: "x" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) -qualifiers_final_annotation.py:169:9 - error: "x" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) -qualifiers_final_annotation.py:180:1 - error: "TEN" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) -qualifiers_final_annotation.py:184:1 - error: "PI" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) +qualifiers_final_annotation.py:178:5 - error: "ID1" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) +qualifiers_final_annotation.py:182:5 - error: "x" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) +qualifiers_final_annotation.py:184:10 - error: "x" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) +qualifiers_final_annotation.py:186:9 - error: "x" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) +qualifiers_final_annotation.py:189:30 - error: "x" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) +qualifiers_final_annotation.py:192:9 - error: "x" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) +qualifiers_final_annotation.py:203:1 - error: "TEN" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) +qualifiers_final_annotation.py:207:1 - error: "PI" is declared as Final and cannot be reassigned (reportGeneralTypeIssues) """ conformance_automated = "Pass" errors_diff = """ diff --git a/conformance/results/results.html b/conformance/results/results.html index 7915147fd..195314d5c 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -994,16 +994,27 @@

Python Type System Conformance Test Results

Partial
    +
  • Infers invalid Literal values from float.
  • Does not treat use of Final name as if it was replaced by the literal in NamedTuple definition.
  • Does not allow conditional assignment of Final instance variable in __init__ method.
  • Does not allow redefinition of private class variable that is marked Final in parent class.
  • Does not report modification of local Final variable via for statement.
+ + Partial +
    +
  • Infers invalid Literal values from float and range.
  • +
+ Pass Pass - Pass - Pass + + Partial +
    +
  • Infers float* instead of float.
  • +
+ Pass @@ -1018,10 +1029,10 @@

Python Type System Conformance Test Results

2 / 3 • 66.7% - 2.5 / 3 • 83.3% - 3 / 3 • 100.0% + 2 / 3 • 66.7% 3 / 3 • 100.0% 3 / 3 • 100.0% + 2.5 / 3 • 83.3% 3 / 3 • 100.0% @@ -2608,10 +2619,10 @@

Python Type System Conformance Test Results

108.5 / 145 • 74.8% - 138 / 145 • 95.2% + 137.5 / 145 • 94.8% 140.5 / 145 • 96.9% 135.5 / 145 • 93.4% - 132 / 145 • 91.0% + 131.5 / 145 • 90.7% 144.5 / 145 • 99.7% diff --git a/conformance/results/ty/qualifiers_final_annotation.toml b/conformance/results/ty/qualifiers_final_annotation.toml index ba871f898..83fb99cee 100644 --- a/conformance/results/ty/qualifiers_final_annotation.toml +++ b/conformance/results/ty/qualifiers_final_annotation.toml @@ -1,35 +1,45 @@ -conformance_automated = "Pass" +conformant = "Partial" +notes = """ +Infers `float*` instead of `float`. +""" +conformance_automated = "Fail" errors_diff = """ +Lines 29, 30: Expected at least one success (tag 'bare3') +Line 29: Unexpected errors ['qualifiers_final_annotation.py:29:1: error[type-assertion-failure] Type `float*` does not match asserted type `float`'] +Line 30: Unexpected errors ['qualifiers_final_annotation.py:30:1: error[type-assertion-failure] Type `float*` does not match asserted type `float`'] """ output = """ -qualifiers_final_annotation.py:16:1: error[final-without-value] `Final` symbol `BAD1` is not assigned a value -qualifiers_final_annotation.py:18:7: error[invalid-type-form] Type qualifier `typing.Final` expected exactly 1 argument, got 2 -qualifiers_final_annotation.py:34:5: error[final-without-value] `Final` symbol `ID2` is not assigned a value -qualifiers_final_annotation.py:38:5: error[final-without-value] `Final` symbol `ID3` is not assigned a value -qualifiers_final_annotation.py:54:9: error[invalid-assignment] Invalid assignment to final attribute: `ID5` already has a value in the class body -qualifiers_final_annotation.py:62:9: error[invalid-assignment] Cannot assign to final attribute `id3` on type `Self@method1`: `Final` attributes can only be assigned in the class body or `__init__` -qualifiers_final_annotation.py:63:9: error[invalid-assignment] Cannot assign to final attribute `id4` on type `Self@method1`: `Final` attributes can only be assigned in the class body or `__init__` -qualifiers_final_annotation.py:65:9: error[invalid-assignment] Cannot assign to final attribute `ID7` on type `Self@method1`: `Final` attributes can only be assigned in the class body or `__init__` -qualifiers_final_annotation.py:67:9: error[invalid-assignment] Cannot assign to final attribute `ID7` on type `Self@method1`: `Final` attributes can only be assigned in the class body or `__init__` -qualifiers_final_annotation.py:71:1: error[invalid-assignment] Reassignment of `Final` symbol `RATE` is not allowed: Symbol later reassigned here -qualifiers_final_annotation.py:81:1: error[invalid-assignment] Cannot assign to final attribute `DEFAULT_ID` on type ``: `Final` attributes can only be assigned in the class body or `__init__` -qualifiers_final_annotation.py:94:5: error[override-of-final-variable] Cannot override final variable `BORDER_WIDTH` from superclass `ClassC` -qualifiers_final_annotation.py:107:13: error[redundant-final-classvar] `Combining `ClassVar` and `Final` is redundant -qualifiers_final_annotation.py:108:13: error[redundant-final-classvar] `Combining `ClassVar` and `Final` is redundant -qualifiers_final_annotation.py:118:9: error[invalid-type-form] Type qualifier `typing.Final` is not allowed in type expressions (only in annotation expressions) -qualifiers_final_annotation.py:121:14: error[invalid-type-form] Type qualifier `typing.Final` is not allowed in parameter annotations -qualifiers_final_annotation.py:131:8: error[invalid-type-form] `Final` is not allowed in TypedDict fields -qualifiers_final_annotation.py:136:5: error[invalid-named-tuple] Type qualifier `Final` is not allowed on NamedTuple field `b` -qualifiers_final_annotation.py:148:1: error[missing-argument] No arguments provided for required parameters `x`, `y` -qualifiers_final_annotation.py:148:3: error[unknown-argument] Argument `a` does not match any known parameter -qualifiers_final_annotation.py:149:3: error[invalid-argument-type] Argument is incorrect: Expected `int`, found `Literal[""]` -qualifiers_final_annotation.py:149:9: error[invalid-argument-type] Argument is incorrect: Expected `int`, found `Literal[""]` -qualifiers_final_annotation.py:155:5: error[invalid-assignment] Reassignment of `Final` symbol `ID1` is not allowed: Reassignment of `Final` symbol -qualifiers_final_annotation.py:159:5: error[invalid-assignment] Reassignment of `Final` symbol `x` is not allowed: Symbol later reassigned here -qualifiers_final_annotation.py:161:10: error[invalid-assignment] Reassignment of `Final` symbol `x` is not allowed: Symbol later reassigned here -qualifiers_final_annotation.py:163:9: error[invalid-assignment] Reassignment of `Final` symbol `x` is not allowed: Symbol later reassigned here -qualifiers_final_annotation.py:166:30: error[invalid-assignment] Reassignment of `Final` symbol `x` is not allowed: Symbol later reassigned here -qualifiers_final_annotation.py:169:9: error[invalid-assignment] Reassignment of `Final` symbol `x` is not allowed: Symbol later reassigned here -qualifiers_final_annotation.py:180:1: error[invalid-assignment] Reassignment of `Final` symbol `TEN` is not allowed: Reassignment of `Final` symbol -qualifiers_final_annotation.py:184:1: error[invalid-assignment] Reassignment of `Final` symbol `PI` is not allowed: Reassignment of `Final` symbol +qualifiers_final_annotation.py:24:1: error[type-assertion-failure] Type `Literal[3]` does not match asserted type `int` +qualifiers_final_annotation.py:29:1: error[type-assertion-failure] Type `float*` does not match asserted type `float` +qualifiers_final_annotation.py:30:1: error[type-assertion-failure] Type `float*` does not match asserted type `float` +qualifiers_final_annotation.py:37:1: error[final-without-value] `Final` symbol `BAD1` is not assigned a value +qualifiers_final_annotation.py:39:7: error[invalid-type-form] Type qualifier `typing.Final` expected exactly 1 argument, got 2 +qualifiers_final_annotation.py:55:5: error[final-without-value] `Final` symbol `ID2` is not assigned a value +qualifiers_final_annotation.py:59:5: error[final-without-value] `Final` symbol `ID3` is not assigned a value +qualifiers_final_annotation.py:75:9: error[invalid-assignment] Invalid assignment to final attribute: `ID5` already has a value in the class body +qualifiers_final_annotation.py:83:9: error[invalid-assignment] Cannot assign to final attribute `id3` on type `Self@method1`: `Final` attributes can only be assigned in the class body or `__init__` +qualifiers_final_annotation.py:84:9: error[invalid-assignment] Cannot assign to final attribute `id4` on type `Self@method1`: `Final` attributes can only be assigned in the class body or `__init__` +qualifiers_final_annotation.py:86:9: error[invalid-assignment] Cannot assign to final attribute `ID7` on type `Self@method1`: `Final` attributes can only be assigned in the class body or `__init__` +qualifiers_final_annotation.py:88:9: error[invalid-assignment] Cannot assign to final attribute `ID7` on type `Self@method1`: `Final` attributes can only be assigned in the class body or `__init__` +qualifiers_final_annotation.py:92:1: error[invalid-assignment] Reassignment of `Final` symbol `RATE` is not allowed: Symbol later reassigned here +qualifiers_final_annotation.py:102:1: error[invalid-assignment] Cannot assign to final attribute `DEFAULT_ID` on type ``: `Final` attributes can only be assigned in the class body or `__init__` +qualifiers_final_annotation.py:115:5: error[override-of-final-variable] Cannot override final variable `BORDER_WIDTH` from superclass `ClassC` +qualifiers_final_annotation.py:128:13: error[redundant-final-classvar] `Combining `ClassVar` and `Final` is redundant +qualifiers_final_annotation.py:129:13: error[redundant-final-classvar] `Combining `ClassVar` and `Final` is redundant +qualifiers_final_annotation.py:139:9: error[invalid-type-form] Type qualifier `typing.Final` is not allowed in type expressions (only in annotation expressions) +qualifiers_final_annotation.py:142:14: error[invalid-type-form] Type qualifier `typing.Final` is not allowed in parameter annotations +qualifiers_final_annotation.py:152:8: error[invalid-type-form] `Final` is not allowed in TypedDict fields +qualifiers_final_annotation.py:157:5: error[invalid-named-tuple] Type qualifier `Final` is not allowed on NamedTuple field `b` +qualifiers_final_annotation.py:169:1: error[missing-argument] No arguments provided for required parameters `x`, `y` +qualifiers_final_annotation.py:169:3: error[unknown-argument] Argument `a` does not match any known parameter +qualifiers_final_annotation.py:170:3: error[invalid-argument-type] Argument is incorrect: Expected `int`, found `Literal[""]` +qualifiers_final_annotation.py:170:9: error[invalid-argument-type] Argument is incorrect: Expected `int`, found `Literal[""]` +qualifiers_final_annotation.py:178:5: error[invalid-assignment] Reassignment of `Final` symbol `ID1` is not allowed: Reassignment of `Final` symbol +qualifiers_final_annotation.py:182:5: error[invalid-assignment] Reassignment of `Final` symbol `x` is not allowed: Symbol later reassigned here +qualifiers_final_annotation.py:184:10: error[invalid-assignment] Reassignment of `Final` symbol `x` is not allowed: Symbol later reassigned here +qualifiers_final_annotation.py:186:9: error[invalid-assignment] Reassignment of `Final` symbol `x` is not allowed: Symbol later reassigned here +qualifiers_final_annotation.py:189:30: error[invalid-assignment] Reassignment of `Final` symbol `x` is not allowed: Symbol later reassigned here +qualifiers_final_annotation.py:192:9: error[invalid-assignment] Reassignment of `Final` symbol `x` is not allowed: Symbol later reassigned here +qualifiers_final_annotation.py:203:1: error[invalid-assignment] Reassignment of `Final` symbol `TEN` is not allowed: Reassignment of `Final` symbol +qualifiers_final_annotation.py:207:1: error[invalid-assignment] Reassignment of `Final` symbol `PI` is not allowed: Reassignment of `Final` symbol """ diff --git a/conformance/results/zuban/qualifiers_final_annotation.toml b/conformance/results/zuban/qualifiers_final_annotation.toml index 1101ba386..a5c6254a1 100644 --- a/conformance/results/zuban/qualifiers_final_annotation.toml +++ b/conformance/results/zuban/qualifiers_final_annotation.toml @@ -2,34 +2,36 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ -qualifiers_final_annotation.py:16: error: Type in Final[...] can only be omitted if there is an initializer [misc] -qualifiers_final_annotation.py:18: error: Final[...] takes at most one type argument [misc] -qualifiers_final_annotation.py:34: error: Type in Final[...] can only be omitted if there is an initializer [misc] -qualifiers_final_annotation.py:38: error: Final name must be initialized with a value [misc] -qualifiers_final_annotation.py:54: error: Cannot assign to final attribute "ID5" [misc] -qualifiers_final_annotation.py:62: error: Can only declare a final attribute in class body or __init__ [misc] -qualifiers_final_annotation.py:63: error: Can only declare a final attribute in class body or __init__ [misc] -qualifiers_final_annotation.py:65: error: Cannot assign to final attribute "ID7" [misc] -qualifiers_final_annotation.py:67: error: Cannot assign to final attribute "ID7" [misc] -qualifiers_final_annotation.py:71: error: Cannot assign to final name "RATE" [misc] -qualifiers_final_annotation.py:81: error: Cannot assign to final attribute "DEFAULT_ID" [misc] -qualifiers_final_annotation.py:94: error: Cannot assign to final name "BORDER_WIDTH" [misc] -qualifiers_final_annotation.py:107: error: Final can be only used as an outermost qualifier in a variable annotation [misc] -qualifiers_final_annotation.py:108: error: Invalid Type: ClassVar nested inside other type [misc] -qualifiers_final_annotation.py:118: error: Final can be only used as an outermost qualifier in a variable annotation [misc] -qualifiers_final_annotation.py:121: error: Final can be only used as an outermost qualifier in a variable annotation [misc] -qualifiers_final_annotation.py:131: error: Final can be only used as an outermost qualifier in a variable annotation [misc] -qualifiers_final_annotation.py:136: error: Final can be only used as an outermost qualifier in a variable annotation [misc] -qualifiers_final_annotation.py:148: error: Unexpected keyword argument "a" for "N" [call-arg] -qualifiers_final_annotation.py:149: error: Argument "x" to "N" has incompatible type "str"; expected "int" [arg-type] -qualifiers_final_annotation.py:149: error: Argument "y" to "N" has incompatible type "str"; expected "int" [arg-type] -qualifiers_final_annotation.py:155: error: Cannot assign to final name "ID1" [misc] -qualifiers_final_annotation.py:159: error: Cannot assign to final name "x" [misc] -qualifiers_final_annotation.py:161: error: Cannot assign to final name "x" [misc] -qualifiers_final_annotation.py:163: error: Cannot assign to final name "x" [misc] -qualifiers_final_annotation.py:166: error: Cannot assign to final name "x" [misc] -qualifiers_final_annotation.py:166: error: Incompatible types in assignment (expression has type "TextIOWrapper[_WrappedBuffer]", variable has type "int") [assignment] -qualifiers_final_annotation.py:169: error: Cannot assign to final name "x" [misc] -qualifiers_final_annotation.py:180: error: Cannot assign to final name "TEN" [misc] -qualifiers_final_annotation.py:184: error: Cannot assign to final name "PI" [misc] +qualifiers_final_annotation.py:24: error: Expression is of type "Literal[3]", not "int" [misc] +qualifiers_final_annotation.py:30: error: Expression is of type "float", not "float | int" [misc] +qualifiers_final_annotation.py:37: error: Type in Final[...] can only be omitted if there is an initializer [misc] +qualifiers_final_annotation.py:39: error: Final[...] takes at most one type argument [misc] +qualifiers_final_annotation.py:55: error: Type in Final[...] can only be omitted if there is an initializer [misc] +qualifiers_final_annotation.py:59: error: Final name must be initialized with a value [misc] +qualifiers_final_annotation.py:75: error: Cannot assign to final attribute "ID5" [misc] +qualifiers_final_annotation.py:83: error: Can only declare a final attribute in class body or __init__ [misc] +qualifiers_final_annotation.py:84: error: Can only declare a final attribute in class body or __init__ [misc] +qualifiers_final_annotation.py:86: error: Cannot assign to final attribute "ID7" [misc] +qualifiers_final_annotation.py:88: error: Cannot assign to final attribute "ID7" [misc] +qualifiers_final_annotation.py:92: error: Cannot assign to final name "RATE" [misc] +qualifiers_final_annotation.py:102: error: Cannot assign to final attribute "DEFAULT_ID" [misc] +qualifiers_final_annotation.py:115: error: Cannot assign to final name "BORDER_WIDTH" [misc] +qualifiers_final_annotation.py:128: error: Final can be only used as an outermost qualifier in a variable annotation [misc] +qualifiers_final_annotation.py:129: error: Invalid Type: ClassVar nested inside other type [misc] +qualifiers_final_annotation.py:139: error: Final can be only used as an outermost qualifier in a variable annotation [misc] +qualifiers_final_annotation.py:142: error: Final can be only used as an outermost qualifier in a variable annotation [misc] +qualifiers_final_annotation.py:152: error: Final can be only used as an outermost qualifier in a variable annotation [misc] +qualifiers_final_annotation.py:157: error: Final can be only used as an outermost qualifier in a variable annotation [misc] +qualifiers_final_annotation.py:169: error: Unexpected keyword argument "a" for "N" [call-arg] +qualifiers_final_annotation.py:170: error: Argument "x" to "N" has incompatible type "str"; expected "int" [arg-type] +qualifiers_final_annotation.py:170: error: Argument "y" to "N" has incompatible type "str"; expected "int" [arg-type] +qualifiers_final_annotation.py:178: error: Cannot assign to final name "ID1" [misc] +qualifiers_final_annotation.py:182: error: Cannot assign to final name "x" [misc] +qualifiers_final_annotation.py:184: error: Cannot assign to final name "x" [misc] +qualifiers_final_annotation.py:186: error: Cannot assign to final name "x" [misc] +qualifiers_final_annotation.py:189: error: Cannot assign to final name "x" [misc] +qualifiers_final_annotation.py:189: error: Incompatible types in assignment (expression has type "TextIOWrapper[_WrappedBuffer]", variable has type "int") [assignment] +qualifiers_final_annotation.py:192: error: Cannot assign to final name "x" [misc] +qualifiers_final_annotation.py:203: error: Cannot assign to final name "TEN" [misc] +qualifiers_final_annotation.py:207: error: Cannot assign to final name "PI" [misc] """ diff --git a/conformance/src/main.py b/conformance/src/main.py index 63f82ea72..be589f1a1 100644 --- a/conformance/src/main.py +++ b/conformance/src/main.py @@ -6,9 +6,9 @@ import re import sys import tomllib +from collections.abc import Sequence from pathlib import Path from time import time -from typing import Sequence import tomlkit @@ -65,7 +65,7 @@ def run_tests( def get_expected_errors(test_case: Path) -> tuple[ dict[int, tuple[int, int]], - dict[str, tuple[list[int], bool]], + dict[str, tuple[list[int], bool, bool]], ]: """Return the line numbers where type checkers are expected to produce an error. @@ -92,7 +92,7 @@ def f(): pass # E[final] with open(test_case, "r", encoding="utf-8") as f: lines = f.readlines() output: dict[int, tuple[int, int]] = {} - groups: dict[str, tuple[list[int], bool]] = {} + groups: dict[str, tuple[list[int], bool, bool]] = {} for i, line in enumerate(lines, start=1): line_without_comment, *_ = line.split("#") # Ignore lines with no non-comment content. This allows commenting out test cases. @@ -111,14 +111,22 @@ def f(): pass # E[final] tag = match.group(1) if tag.endswith("+"): allow_multiple = True + require_success = False + tag = tag[:-1] + elif tag.endswith("!"): + allow_multiple = True + require_success = True tag = tag[:-1] else: allow_multiple = False + require_success = False if tag not in groups: - groups[tag] = ([i], allow_multiple) + groups[tag] = ([i], allow_multiple, require_success) else: if groups[tag][1] != allow_multiple: raise ValueError(f"Error group {tag} has inconsistent allow_multiple value in {test_case}") + if groups[tag][2] != require_success: + raise ValueError(f"Error group {tag} has inconsistent require_success value in {test_case}") groups[tag][0].append(i) for group, linenos in groups.items(): if len(linenos) == 1: @@ -152,11 +160,13 @@ def diff_expected_errors( # We don't report an issue if the count differs, because type checkers may produce # multiple error messages for a single line. linenos_used_by_groups: set[int] = set() - for group, (linenos, allow_multiple) in error_groups.items(): + for group, (linenos, allow_multiple, require_success) in error_groups.items(): num_errors = sum(1 for lineno in linenos if lineno in errors) - if num_errors == 0: + if require_success and num_errors == len(linenos): + differences.append(f"Lines {', '.join(map(str, linenos))}: Expected at least one success (tag {group!r})") + elif num_errors == 0 and not require_success: differences.append(f"Lines {', '.join(map(str, linenos))}: Expected error (tag {group!r})") - elif num_errors == 1 or allow_multiple: + elif num_errors == 1 or allow_multiple or require_success: linenos_used_by_groups.update(linenos) else: differences.append(f"Lines {', '.join(map(str, linenos))}: Expected exactly one error (tag {group!r})") diff --git a/conformance/tests/literals_interactions.py b/conformance/tests/literals_interactions.py index 474126768..2b84b2a32 100644 --- a/conformance/tests/literals_interactions.py +++ b/conformance/tests/literals_interactions.py @@ -134,10 +134,3 @@ def parse_status3(status: str) -> None: if status == "PENDING": expects_pending_status(status) # E? narrowing the type here is unsound, but allowed per the spec - - -final_val1: Final = 3 -assert_type(final_val1, Literal[3]) - -final_val2: Final = True -assert_type(final_val2, Literal[True]) diff --git a/conformance/tests/qualifiers_final_annotation.py b/conformance/tests/qualifiers_final_annotation.py index 0dc611211..b85d644fb 100644 --- a/conformance/tests/qualifiers_final_annotation.py +++ b/conformance/tests/qualifiers_final_annotation.py @@ -6,10 +6,31 @@ # Specification: https://typing.readthedocs.io/en/latest/spec/qualifiers.html#id1 -ID1: Final[int] = 1 +# > If the value is a literal value which is a valid parameter for +# > Literal[...], type checkers should infer that Literal. -ID2: Final = 1 -assert_type(ID2, Literal[1]) +bare1_1: Final = 3 +assert_type(bare1_1, Literal[3]) + +bare1_2: Final = True +assert_type(bare1_2, Literal[True]) + +# > If the value is an expression whose result is a valid parameter for +# > Literal[...], type checkers may infer that Literal or use standard +# > inference rules. + +bare2: Final = 1 + 2 +assert_type(bare2, Literal[3]) # E[bare2]: either Literal[3] or int +assert_type(bare2, int) # E[bare2]: either Literal[3] or int + +# > In all other cases, type checkers should use standard inference rules. + +bare3: Final = 3.14 # infer bare3 as Final[float] or Final[float | int] +assert_type(bare3, float) # E[bare3!]: either float or float | int +assert_type(bare3, float | int) # E[bare3!]: either float or float | int + +bare4: Final = range(3) +assert_type(bare4, range) # > If the right hand side is omitted, there must be an explicit type argument to Final. @@ -68,7 +89,7 @@ def method1(self) -> None: RATE: Final = 3000 -RATE = 300 # E: Cannot redefine Final value +RATE = 300 # E: Cannot redefine Final # > There can’t be separate class-level and instance-level constants # > with the same name. @@ -149,6 +170,8 @@ class NTWithFinal(NamedTuple): N(x="", y="") # E +ID1: Final = 1 + def func2() -> None: global ID1 diff --git a/docs/spec/distributing.rst b/docs/spec/distributing.rst index 13cfff81a..85736219f 100644 --- a/docs/spec/distributing.rst +++ b/docs/spec/distributing.rst @@ -105,7 +105,7 @@ assignments:: x = 0 # type: int x = ... # type: int -The :ref:`Literal shortcut using Final ` should be +The :ref:`Literal shortcut using Final ` should be supported:: x: Final = 0 # type is Literal[0] diff --git a/docs/spec/literal.rst b/docs/spec/literal.rst index 0eb93c27a..8912dd2b5 100644 --- a/docs/spec/literal.rst +++ b/docs/spec/literal.rst @@ -499,44 +499,10 @@ involving Literal bools. For example, we can combine ``Literal[True]``, else: scalar += "foo" # Type checks: type of 'scalar' is narrowed to 'str' -.. _literal-final-interactions: - Interactions with Final """"""""""""""""""""""" -The ``Final`` qualifier can be used to declare that some variable or -attribute cannot be reassigned:: - - foo: Final = 3 - foo = 4 # Error: 'foo' is declared to be Final - -Note that in the example above, we know that ``foo`` will always be equal to -exactly ``3``. A type checker can use this information to deduce that ``foo`` -is valid to use in any context that expects a ``Literal[3]``:: - - def expects_three(x: Literal[3]) -> None: ... - - expects_three(foo) # Type checks, since 'foo' is Final and equal to 3 - -The ``Final`` qualifier serves as a shorthand for declaring that a variable -is *effectively Literal*. - -Type checkers are expected to -support this shortcut. Specifically, given a variable or attribute assignment -of the form ``var: Final = value`` where ``value`` is a valid parameter for -``Literal[...]``, type checkers should understand that ``var`` may be used in -any context that expects a ``Literal[value]``. - -Type checkers are not obligated to understand any other uses of Final. For -example, whether or not the following program type checks is left unspecified:: - - # Note: The assignment does not exactly match the form 'var: Final = value'. - bar1: Final[int] = 3 - expects_three(bar1) # May or may not be accepted by type checkers - - # Note: "Literal[1 + 2]" is not a legal type. - bar2: Final = 1 + 2 - expects_three(bar2) # May or may not be accepted by type checkers +See the :ref:`final-inference` section in the :ref:`type-qualifiers` chapter. .. _`literalstring`: diff --git a/docs/spec/qualifiers.rst b/docs/spec/qualifiers.rst index 6814692e0..f2fecbbbc 100644 --- a/docs/spec/qualifiers.rst +++ b/docs/spec/qualifiers.rst @@ -91,8 +91,7 @@ Syntax ID: Final = 1 - The typechecker should apply its usual type inference mechanisms to - determine the type of ``ID`` (here, likely, ``int``). Note that unlike for + Note that unlike for generic classes this is *not* the same as ``Final[Any]``. * In class bodies and stub files you can omit the right hand side and just write @@ -159,14 +158,6 @@ The generated ``__init__`` method of :doc:`dataclasses` qualifies for this requirement: a bare ``x: Final[int]`` is permitted in a dataclass body, because the generated ``__init__`` will initialize ``x``. -Type checkers should infer a final attribute that is initialized in a class -body as being a class variable, except in the case of :doc:`dataclasses`, where -``x: Final[int] = 3`` creates a dataclass field and instance-level final -attribute ``x`` with default value ``3``; ``x: ClassVar[Final[int]] = 3`` is -necessary to create a final class variable with value ``3``. In -non-dataclasses, combining ``ClassVar`` and ``Final`` is redundant, and type -checkers may choose to warn or error on the redundancy. - ``Final`` may only be used in assignments or variable annotations. Using it in any other position is an error. In particular, ``Final`` can't be used in annotations for function arguments:: @@ -207,6 +198,55 @@ following should be allowed:: item or a :ref:`NamedTuple ` field. Such usage also generates an error at runtime. +.. _`final-inference`: + +Inference Rules +^^^^^^^^^^^^^^^ + +Type checkers should use the following inference rules for ``Final`` without a +type annotation: + +* If the value is a literal value which is a valid parameter for + ``Literal[...]``, type checkers should infer that ``Literal``. For example:: + + bare1: Final = 3 # infer bare1 as Final[Literal[3]] + +* If the value is an expression whose result is a valid parameter for + ``Literal[...]``, type checkers may infer that ``Literal`` or use standard + inference rules. For example:: + + bare2: Final = 1 + 2 # may infer bare2 as Final[Literal[3]] or Final[int] + +* In all other cases, type checkers should use standard inference rules. + For example:: + + bare3: Final = 3.14 # infer bare3 as Final[float] or Final[float | int] + bare4: Final = range(3) # infer bare4 as Final[range] + +Type checkers should use the following inference rules for ``Final`` with an +explicit type: + +* If the right hand side is missing, type checkers should use the explicit + type:: + + typed1: Final[int] # infer typed1 as Final[int] + +* Type checkers are not obligated to understand any other uses of Final. For + example, whether or not the following program type checks is left + unspecified:: + + # Note: The assignment does not exactly match the form 'var: Final = value'. + typed2: Final[int] = 3 + expects_three(typed2) # May or may not be accepted by type checkers + +Type checkers should infer a final attribute that is initialized in a class +body as being a class variable, except in the case of :doc:`dataclasses`, where +``x: Final[int] = 3`` creates a dataclass field and instance-level final +attribute ``x`` with default value ``3``; ``x: ClassVar[Final[int]] = 3`` is +necessary to create a final class variable with value ``3``. In +non-dataclasses, combining ``ClassVar`` and ``Final`` is redundant, and type +checkers may choose to warn or error on the redundancy. + Importing ``Final`` Variables ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^