From 52aad76a5a606562d28d404ee7c113fc42c390b4 Mon Sep 17 00:00:00 2001
From: Sam Goldman <samgoldman@meta.com>
Date: Thu, 30 Jan 2025 21:15:21 -0800
Subject: [PATCH 1/3] Add conformance test for @final-decorated @property

The language of the typing spec indicates that the @final decorator
may be used with properties:

> The method decorator version may be used with all of instance methods, class methods, static methods, and properties.

I noticed this case while working on Pyre. I observed that Mypy and
Pyright also differ in behavior, so it seemed like a good conformance
test to add.

See discussion here:
https://discuss.python.org/t/proposal-allow-chaining-final-decorator-when-previous-decorators-return-a-non-function/78918
---
 .../mypy/qualifiers_final_decorator.toml      |  29 ++--
 conformance/results/mypy/version.toml         |   4 +-
 .../pyre/qualifiers_final_decorator.toml      |  21 +--
 conformance/results/pyre/version.toml         |   2 +-
 .../results/pyright/aliases_explicit.toml     |  10 +-
 .../pyright/aliases_type_statement.toml       |  10 +-
 .../pyright/aliases_typealiastype.toml        |   2 +-
 .../pyright/annotations_forward_refs.toml     |  10 +-
 .../results/pyright/annotations_typeexpr.toml |  10 +-
 .../pyright/generics_syntax_declarations.toml |   2 +-
 .../pyright/generics_variance_inference.toml  |   9 +-
 .../results/pyright/qualifiers_annotated.toml |   2 +-
 .../pyright/qualifiers_final_decorator.toml   |  23 +--
 conformance/results/pyright/version.toml      |   4 +-
 .../pytype/qualifiers_final_decorator.toml    | 132 +++++++++++++++---
 conformance/results/pytype/version.toml       |   2 +-
 conformance/results/results.html              |  12 +-
 .../tests/qualifiers_final_decorator.py       |  12 ++
 18 files changed, 198 insertions(+), 98 deletions(-)

diff --git a/conformance/results/mypy/qualifiers_final_decorator.toml b/conformance/results/mypy/qualifiers_final_decorator.toml
index e25fa2c8..514606bb 100644
--- a/conformance/results/mypy/qualifiers_final_decorator.toml
+++ b/conformance/results/mypy/qualifiers_final_decorator.toml
@@ -1,20 +1,21 @@
 conformant = "Pass"
 output = """
 qualifiers_final_decorator.py:21: error: Cannot inherit from final class "Base1"  [misc]
-qualifiers_final_decorator.py:56: error: Cannot override final attribute "method1" (previously declared in base class "Base2")  [misc]
-qualifiers_final_decorator.py:59: error: Cannot override final attribute "method2" (previously declared in base class "Base2")  [misc]
-qualifiers_final_decorator.py:63: error: Cannot override final attribute "method3" (previously declared in base class "Base2")  [misc]
-qualifiers_final_decorator.py:67: error: Cannot override final attribute "method4" (previously declared in base class "Base2")  [misc]
-qualifiers_final_decorator.py:80: error: Cannot override final attribute "method" (previously declared in base class "Base3")  [misc]
-qualifiers_final_decorator.py:84: error: @final should be applied only to overload implementation  [misc]
-qualifiers_final_decorator.py:94: error: Cannot override final attribute "method" (previously declared in base class "Base4")  [misc]
-qualifiers_final_decorator.py:118: error: Cannot override final attribute "method" (previously declared in base class "Base5_2")  [misc]
-qualifiers_final_decorator.py:118: error: Signature of "method" incompatible with supertype "Base5_2"  [override]
-qualifiers_final_decorator.py:118: note:      Superclass:
-qualifiers_final_decorator.py:118: note:          def method(self, v: int) -> None
-qualifiers_final_decorator.py:118: note:      Subclass:
-qualifiers_final_decorator.py:118: note:          def method(self) -> None
-qualifiers_final_decorator.py:125: error: @final cannot be used with non-method functions  [misc]
+qualifiers_final_decorator.py:64: error: Cannot override final attribute "method1" (previously declared in base class "Base2")  [misc]
+qualifiers_final_decorator.py:67: error: Cannot override final attribute "method2" (previously declared in base class "Base2")  [misc]
+qualifiers_final_decorator.py:71: error: Cannot override final attribute "method3" (previously declared in base class "Base2")  [misc]
+qualifiers_final_decorator.py:75: error: Cannot override final attribute "method4" (previously declared in base class "Base2")  [misc]
+qualifiers_final_decorator.py:86: error: Cannot override final attribute "method5" (previously declared in base class "Base2")  [misc]
+qualifiers_final_decorator.py:92: error: Cannot override final attribute "method" (previously declared in base class "Base3")  [misc]
+qualifiers_final_decorator.py:96: error: @final should be applied only to overload implementation  [misc]
+qualifiers_final_decorator.py:106: error: Cannot override final attribute "method" (previously declared in base class "Base4")  [misc]
+qualifiers_final_decorator.py:130: error: Cannot override final attribute "method" (previously declared in base class "Base5_2")  [misc]
+qualifiers_final_decorator.py:130: error: Signature of "method" incompatible with supertype "Base5_2"  [override]
+qualifiers_final_decorator.py:130: note:      Superclass:
+qualifiers_final_decorator.py:130: note:          def method(self, v: int) -> None
+qualifiers_final_decorator.py:130: note:      Subclass:
+qualifiers_final_decorator.py:130: note:          def method(self) -> None
+qualifiers_final_decorator.py:137: error: @final cannot be used with non-method functions  [misc]
 """
 conformance_automated = "Pass"
 errors_diff = """
diff --git a/conformance/results/mypy/version.toml b/conformance/results/mypy/version.toml
index 3d498066..97e385c3 100644
--- a/conformance/results/mypy/version.toml
+++ b/conformance/results/mypy/version.toml
@@ -1,2 +1,2 @@
-version = "mypy 1.14.0"
-test_duration = 1.6
+version = "mypy 1.14.1"
+test_duration = 3.3
diff --git a/conformance/results/pyre/qualifiers_final_decorator.toml b/conformance/results/pyre/qualifiers_final_decorator.toml
index ef5be734..137d2a2b 100644
--- a/conformance/results/pyre/qualifiers_final_decorator.toml
+++ b/conformance/results/pyre/qualifiers_final_decorator.toml
@@ -7,18 +7,19 @@ Reports misleading error when overload is marked @final but implementation is no
 output = """
 qualifiers_final_decorator.py:21:0 Invalid inheritance [39]: Cannot inherit from final class `Base1`.
 qualifiers_final_decorator.py:51:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
-qualifiers_final_decorator.py:56:4 Invalid override [40]: `qualifiers_final_decorator.Derived2.method1` cannot override final method defined in `Base2`.
-qualifiers_final_decorator.py:60:4 Invalid override [40]: `qualifiers_final_decorator.Derived2.method2` cannot override final method defined in `Base2`.
-qualifiers_final_decorator.py:64:4 Invalid override [40]: `qualifiers_final_decorator.Derived2.method3` cannot override final method defined in `Base2`.
-qualifiers_final_decorator.py:75:4 Invalid override [40]: `qualifiers_final_decorator.Derived2.method4` cannot override final method defined in `Base2`.
-qualifiers_final_decorator.py:86:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
-qualifiers_final_decorator.py:118:4 Inconsistent override [14]: `qualifiers_final_decorator.Derived5.method` overrides method defined in `Base5_2` inconsistently. Could not find parameter `v` in overriding signature.
-qualifiers_final_decorator.py:118:4 Invalid override [40]: `qualifiers_final_decorator.Derived5.method` cannot override final method defined in `Base5_2`.
-qualifiers_final_decorator.py:126:0 Invalid inheritance [39]: `final` cannot be used with non-method functions.
+qualifiers_final_decorator.py:64:4 Invalid override [40]: `qualifiers_final_decorator.Derived2.method1` cannot override final method defined in `Base2`.
+qualifiers_final_decorator.py:68:4 Invalid override [40]: `qualifiers_final_decorator.Derived2.method2` cannot override final method defined in `Base2`.
+qualifiers_final_decorator.py:72:4 Invalid override [40]: `qualifiers_final_decorator.Derived2.method3` cannot override final method defined in `Base2`.
+qualifiers_final_decorator.py:83:4 Invalid override [40]: `qualifiers_final_decorator.Derived2.method4` cannot override final method defined in `Base2`.
+qualifiers_final_decorator.py:98:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
+qualifiers_final_decorator.py:130:4 Inconsistent override [14]: `qualifiers_final_decorator.Derived5.method` overrides method defined in `Base5_2` inconsistently. Could not find parameter `v` in overriding signature.
+qualifiers_final_decorator.py:130:4 Invalid override [40]: `qualifiers_final_decorator.Derived5.method` cannot override final method defined in `Base5_2`.
+qualifiers_final_decorator.py:138:0 Invalid inheritance [39]: `final` cannot be used with non-method functions.
 """
 conformance_automated = "Fail"
 errors_diff = """
-Lines 80, 89: Expected error (tag 'Derived3')
-Lines 94, 102: Expected error (tag 'Derived4')
+Lines 86, 87: Expected error (tag 'method5')
+Lines 92, 101: Expected error (tag 'Derived3')
+Lines 106, 114: Expected error (tag 'Derived4')
 Line 51: Unexpected errors ['qualifiers_final_decorator.py:51:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).']
 """
diff --git a/conformance/results/pyre/version.toml b/conformance/results/pyre/version.toml
index 94de3055..be241112 100644
--- a/conformance/results/pyre/version.toml
+++ b/conformance/results/pyre/version.toml
@@ -1,2 +1,2 @@
 version = "pyre 0.9.23"
-test_duration = 7.3
+test_duration = 10.0
diff --git a/conformance/results/pyright/aliases_explicit.toml b/conformance/results/pyright/aliases_explicit.toml
index a1e82c9e..5948d8ab 100644
--- a/conformance/results/pyright/aliases_explicit.toml
+++ b/conformance/results/pyright/aliases_explicit.toml
@@ -10,25 +10,25 @@ aliases_explicit.py:79:21 - error: Invalid expression form for type alias defini
 aliases_explicit.py:79:21 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
 aliases_explicit.py:80:21 - error: Invalid expression form for type alias definition (reportInvalidTypeForm)
 aliases_explicit.py:80:21 - error: List expression not allowed in type expression
-  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 aliases_explicit.py:80:21 - error: Expected class but received "list[Unknown]" (reportGeneralTypeIssues)
 aliases_explicit.py:81:21 - error: Invalid expression form for type alias definition (reportInvalidTypeForm)
 aliases_explicit.py:81:21 - error: Tuple expression not allowed in type expression
-  Use tuple[T1, ..., Tn] to indicate a tuple type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use tuple[T1, ..., Tn] to indicate a tuple type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 aliases_explicit.py:82:21 - error: Invalid expression form for type alias definition (reportInvalidTypeForm)
 aliases_explicit.py:82:21 - error: List expression not allowed in type expression
-  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 aliases_explicit.py:82:21 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
 aliases_explicit.py:83:21 - error: Invalid expression form for type alias definition (reportInvalidTypeForm)
 aliases_explicit.py:83:21 - error: Dictionary expression not allowed in type expression
-  Use Dict[T1, T2] to indicate a dictionary type (reportInvalidTypeForm)
+  Use dict[T1, T2] to indicate a dictionary type (reportInvalidTypeForm)
 aliases_explicit.py:83:21 - error: Expected class but received "dict[str, Unknown]" (reportGeneralTypeIssues)
 aliases_explicit.py:83:28 - error: "b" is not defined (reportUndefinedVariable)
 aliases_explicit.py:84:21 - error: Invalid expression form for type alias definition (reportInvalidTypeForm)
 aliases_explicit.py:84:21 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
 aliases_explicit.py:85:21 - error: Invalid expression form for type alias definition (reportInvalidTypeForm)
 aliases_explicit.py:85:21 - error: List expression not allowed in type expression
-  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 aliases_explicit.py:85:21 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
 aliases_explicit.py:85:27 - error: Expected class but received "Literal[0]" (reportGeneralTypeIssues)
 aliases_explicit.py:86:21 - error: Invalid expression form for type alias definition (reportInvalidTypeForm)
diff --git a/conformance/results/pyright/aliases_type_statement.toml b/conformance/results/pyright/aliases_type_statement.toml
index 4556366e..34269c47 100644
--- a/conformance/results/pyright/aliases_type_statement.toml
+++ b/conformance/results/pyright/aliases_type_statement.toml
@@ -14,20 +14,20 @@ aliases_type_statement.py:31:22 - error: Argument of type "TypeAliasType" cannot
     "TypeAliasType" is not assignable to "tuple[_ClassInfo, ...]" (reportArgumentType)
 aliases_type_statement.py:37:22 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
 aliases_type_statement.py:38:22 - error: List expression not allowed in type expression
-  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 aliases_type_statement.py:38:22 - error: Expected class but received "list[Unknown]" (reportGeneralTypeIssues)
 aliases_type_statement.py:39:22 - error: Tuple expression not allowed in type expression
-  Use tuple[T1, ..., Tn] to indicate a tuple type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use tuple[T1, ..., Tn] to indicate a tuple type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 aliases_type_statement.py:40:22 - error: List expression not allowed in type expression
-  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 aliases_type_statement.py:40:22 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
 aliases_type_statement.py:41:22 - error: Dictionary expression not allowed in type expression
-  Use Dict[T1, T2] to indicate a dictionary type (reportInvalidTypeForm)
+  Use dict[T1, T2] to indicate a dictionary type (reportInvalidTypeForm)
 aliases_type_statement.py:41:22 - error: Expected class but received "dict[str, Unknown]" (reportGeneralTypeIssues)
 aliases_type_statement.py:41:29 - error: "b" is not defined (reportUndefinedVariable)
 aliases_type_statement.py:42:22 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
 aliases_type_statement.py:43:22 - error: List expression not allowed in type expression
-  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 aliases_type_statement.py:43:22 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
 aliases_type_statement.py:43:28 - error: Expected class but received "Literal[0]" (reportGeneralTypeIssues)
 aliases_type_statement.py:44:22 - error: Ternary expression not allowed in type expression (reportInvalidTypeForm)
diff --git a/conformance/results/pyright/aliases_typealiastype.toml b/conformance/results/pyright/aliases_typealiastype.toml
index 64ebf8cf..610c1a96 100644
--- a/conformance/results/pyright/aliases_typealiastype.toml
+++ b/conformance/results/pyright/aliases_typealiastype.toml
@@ -19,7 +19,7 @@ aliases_typealiastype.py:56:42 - error: Expected class but received "dict[str, U
 aliases_typealiastype.py:56:49 - error: "b" is not defined (reportUndefinedVariable)
 aliases_typealiastype.py:57:42 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
 aliases_typealiastype.py:58:42 - error: List expression not allowed in type expression
-  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 aliases_typealiastype.py:58:42 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
 aliases_typealiastype.py:58:48 - error: Expected class but received "Literal[0]" (reportGeneralTypeIssues)
 aliases_typealiastype.py:59:42 - error: Ternary expression not allowed in type expression (reportInvalidTypeForm)
diff --git a/conformance/results/pyright/annotations_forward_refs.toml b/conformance/results/pyright/annotations_forward_refs.toml
index 29709674..ca35b5bb 100644
--- a/conformance/results/pyright/annotations_forward_refs.toml
+++ b/conformance/results/pyright/annotations_forward_refs.toml
@@ -6,19 +6,19 @@ annotations_forward_refs.py:24:7 - error: Union syntax cannot be used with strin
 annotations_forward_refs.py:25:13 - error: Union syntax cannot be used with string operand; use quotes around entire expression (reportGeneralTypeIssues)
 annotations_forward_refs.py:41:10 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
 annotations_forward_refs.py:42:10 - error: List expression not allowed in type expression
-  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 annotations_forward_refs.py:42:10 - error: Expected class but received "list[Unknown]" (reportGeneralTypeIssues)
 annotations_forward_refs.py:43:10 - error: Tuple expression not allowed in type expression
-  Use tuple[T1, ..., Tn] to indicate a tuple type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use tuple[T1, ..., Tn] to indicate a tuple type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 annotations_forward_refs.py:44:10 - error: List expression not allowed in type expression
-  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 annotations_forward_refs.py:44:10 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
 annotations_forward_refs.py:45:10 - error: Dictionary expression not allowed in type expression
-  Use Dict[T1, T2] to indicate a dictionary type (reportInvalidTypeForm)
+  Use dict[T1, T2] to indicate a dictionary type (reportInvalidTypeForm)
 annotations_forward_refs.py:45:10 - error: Expected class but received "dict[Unknown, Unknown]" (reportGeneralTypeIssues)
 annotations_forward_refs.py:46:10 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
 annotations_forward_refs.py:47:10 - error: List expression not allowed in type expression
-  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 annotations_forward_refs.py:47:10 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
 annotations_forward_refs.py:47:16 - error: Expected class but received "Literal[0]" (reportGeneralTypeIssues)
 annotations_forward_refs.py:48:10 - error: Ternary expression not allowed in type expression (reportInvalidTypeForm)
diff --git a/conformance/results/pyright/annotations_typeexpr.toml b/conformance/results/pyright/annotations_typeexpr.toml
index 5504e946..e9e3fdca 100644
--- a/conformance/results/pyright/annotations_typeexpr.toml
+++ b/conformance/results/pyright/annotations_typeexpr.toml
@@ -2,19 +2,19 @@ conformant = "Pass"
 output = """
 annotations_typeexpr.py:88:9 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
 annotations_typeexpr.py:89:9 - error: List expression not allowed in type expression
-  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 annotations_typeexpr.py:89:9 - error: Expected class but received "list[Unknown]" (reportGeneralTypeIssues)
 annotations_typeexpr.py:90:9 - error: Tuple expression not allowed in type expression
-  Use tuple[T1, ..., Tn] to indicate a tuple type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use tuple[T1, ..., Tn] to indicate a tuple type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 annotations_typeexpr.py:91:9 - error: List expression not allowed in type expression
-  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 annotations_typeexpr.py:91:9 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
 annotations_typeexpr.py:92:9 - error: Dictionary expression not allowed in type expression
-  Use Dict[T1, T2] to indicate a dictionary type (reportInvalidTypeForm)
+  Use dict[T1, T2] to indicate a dictionary type (reportInvalidTypeForm)
 annotations_typeexpr.py:92:9 - error: Expected class but received "dict[Unknown, Unknown]" (reportGeneralTypeIssues)
 annotations_typeexpr.py:93:9 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
 annotations_typeexpr.py:94:9 - error: List expression not allowed in type expression
-  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 annotations_typeexpr.py:94:9 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
 annotations_typeexpr.py:94:15 - error: Expected class but received "Literal[0]" (reportGeneralTypeIssues)
 annotations_typeexpr.py:95:9 - error: Ternary expression not allowed in type expression (reportInvalidTypeForm)
diff --git a/conformance/results/pyright/generics_syntax_declarations.toml b/conformance/results/pyright/generics_syntax_declarations.toml
index 25db9152..bc076dc9 100644
--- a/conformance/results/pyright/generics_syntax_declarations.toml
+++ b/conformance/results/pyright/generics_syntax_declarations.toml
@@ -6,7 +6,7 @@ generics_syntax_declarations.py:32:11 - error: Cannot access attribute "is_integ
   Attribute "is_integer" is unknown (reportAttributeAccessIssue)
 generics_syntax_declarations.py:44:21 - error: TypeVar constraint type cannot be generic (reportGeneralTypeIssues)
 generics_syntax_declarations.py:48:17 - error: List expression not allowed in type expression
-  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 generics_syntax_declarations.py:48:17 - error: Expected class but received "list[Unknown]" (reportGeneralTypeIssues)
 generics_syntax_declarations.py:60:17 - error: TypeVar must have at least two constrained types (reportGeneralTypeIssues)
 generics_syntax_declarations.py:64:17 - error: TypeVar must have at least two constrained types (reportGeneralTypeIssues)
diff --git a/conformance/results/pyright/generics_variance_inference.toml b/conformance/results/pyright/generics_variance_inference.toml
index 5c0f32e2..9a378ad6 100644
--- a/conformance/results/pyright/generics_variance_inference.toml
+++ b/conformance/results/pyright/generics_variance_inference.toml
@@ -23,12 +23,10 @@ generics_variance_inference.py:58:35 - error: Type "ShouldBeCovariant3[float]" i
   "ShouldBeCovariant3[float]" is not assignable to "ShouldBeCovariant3[int]"
     Type parameter "T@ShouldBeCovariant3" is covariant, but "float" is not a subtype of "int"
       "float" is not assignable to "int" (reportAssignmentType)
-generics_variance_inference.py:66:36 - error: Type "ShouldBeCovariant4[int]" is not assignable to declared type "ShouldBeCovariant4[float]"
-  "ShouldBeCovariant4[int]" is not assignable to "ShouldBeCovariant4[float]"
-    Type parameter "T@ShouldBeCovariant4" is invariant, but "int" is not the same as "float" (reportAssignmentType)
 generics_variance_inference.py:67:34 - error: Type "ShouldBeCovariant4[float]" is not assignable to declared type "ShouldBeCovariant4[int]"
   "ShouldBeCovariant4[float]" is not assignable to "ShouldBeCovariant4[int]"
-    Type parameter "T@ShouldBeCovariant4" is invariant, but "float" is not the same as "int" (reportAssignmentType)
+    Type parameter "T@ShouldBeCovariant4" is covariant, but "float" is not a subtype of "int"
+      "float" is not assignable to "int" (reportAssignmentType)
 generics_variance_inference.py:80:34 - error: Type "ShouldBeCovariant5[float]" is not assignable to declared type "ShouldBeCovariant5[int]"
   "ShouldBeCovariant5[float]" is not assignable to "ShouldBeCovariant5[int]"
     Type parameter "T@ShouldBeCovariant5" is covariant, but "float" is not a subtype of "int"
@@ -82,7 +80,6 @@ generics_variance_inference.py:194:37 - error: Type "ShouldBeContravariant2[int]
     Type parameter "T@ShouldBeContravariant2" is contravariant, but "int" is not a supertype of "float"
       "float" is not assignable to "int" (reportAssignmentType)
 """
-conformance_automated = "Fail"
+conformance_automated = "Pass"
 errors_diff = """
-Line 66: Unexpected errors ['generics_variance_inference.py:66:36 - error: Type "ShouldBeCovariant4[int]" is not assignable to declared type "ShouldBeCovariant4[float]"']
 """
diff --git a/conformance/results/pyright/qualifiers_annotated.toml b/conformance/results/pyright/qualifiers_annotated.toml
index b8c271f0..c7f60d82 100644
--- a/conformance/results/pyright/qualifiers_annotated.toml
+++ b/conformance/results/pyright/qualifiers_annotated.toml
@@ -9,7 +9,7 @@ qualifiers_annotated.py:46:17 - error: Dictionary expression not allowed in type
 qualifiers_annotated.py:46:24 - error: "b" is not defined (reportUndefinedVariable)
 qualifiers_annotated.py:47:17 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
 qualifiers_annotated.py:48:17 - error: List expression not allowed in type expression
-  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
+  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
 qualifiers_annotated.py:48:17 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
 qualifiers_annotated.py:48:23 - error: Expected class but received "Literal[0]" (reportGeneralTypeIssues)
 qualifiers_annotated.py:49:17 - error: Ternary expression not allowed in type expression (reportInvalidTypeForm)
diff --git a/conformance/results/pyright/qualifiers_final_decorator.toml b/conformance/results/pyright/qualifiers_final_decorator.toml
index 6a315650..11519dfa 100644
--- a/conformance/results/pyright/qualifiers_final_decorator.toml
+++ b/conformance/results/pyright/qualifiers_final_decorator.toml
@@ -2,20 +2,21 @@ conformant = "Pass"
 output = """
 qualifiers_final_decorator.py:8:6 - warning: Import "_qualifiers_final_decorator" could not be resolved from source (reportMissingModuleSource)
 qualifiers_final_decorator.py:21:16 - error: Base class "Base1" is marked final and cannot be subclassed (reportGeneralTypeIssues)
-qualifiers_final_decorator.py:56:9 - error: Method "method1" cannot override final method defined in class "Base2" (reportIncompatibleMethodOverride)
-qualifiers_final_decorator.py:60:9 - error: Method "method2" cannot override final method defined in class "Base2" (reportIncompatibleMethodOverride)
-qualifiers_final_decorator.py:64:9 - error: Method "method3" cannot override final method defined in class "Base2" (reportIncompatibleMethodOverride)
-qualifiers_final_decorator.py:75:9 - error: Method "method4" cannot override final method defined in class "Base2" (reportIncompatibleMethodOverride)
-qualifiers_final_decorator.py:86:9 - error: Overload for "method" is marked @final but implementation is not (reportInconsistentOverload)
-qualifiers_final_decorator.py:89:9 - error: Method "method" cannot override final method defined in class "Base3" (reportIncompatibleMethodOverride)
-qualifiers_final_decorator.py:102:9 - error: Method "method" cannot override final method defined in class "Base4" (reportIncompatibleMethodOverride)
-qualifiers_final_decorator.py:118:9 - error: Method "method" cannot override final method defined in class "Base5_2" (reportIncompatibleMethodOverride)
-qualifiers_final_decorator.py:118:9 - error: Method "method" overrides class "Base5_2" in an incompatible manner
+qualifiers_final_decorator.py:64:9 - error: Method "method1" cannot override final method defined in class "Base2" (reportIncompatibleMethodOverride)
+qualifiers_final_decorator.py:68:9 - error: Method "method2" cannot override final method defined in class "Base2" (reportIncompatibleMethodOverride)
+qualifiers_final_decorator.py:72:9 - error: Method "method3" cannot override final method defined in class "Base2" (reportIncompatibleMethodOverride)
+qualifiers_final_decorator.py:83:9 - error: Method "method4" cannot override final method defined in class "Base2" (reportIncompatibleMethodOverride)
+qualifiers_final_decorator.py:98:9 - error: @final decorator should be applied only to the implementation (reportInconsistentOverload)
+qualifiers_final_decorator.py:101:9 - error: Method "method" cannot override final method defined in class "Base3" (reportIncompatibleMethodOverride)
+qualifiers_final_decorator.py:114:9 - error: Method "method" cannot override final method defined in class "Base4" (reportIncompatibleMethodOverride)
+qualifiers_final_decorator.py:130:9 - error: Method "method" cannot override final method defined in class "Base5_2" (reportIncompatibleMethodOverride)
+qualifiers_final_decorator.py:130:9 - error: Method "method" overrides class "Base5_2" in an incompatible manner
   Positional parameter count mismatch; base method has 2, but override has 1
   Parameter 2 mismatch: base parameter "v" is keyword parameter, override parameter is position-only (reportIncompatibleMethodOverride)
-qualifiers_final_decorator.py:126:5 - error: Function "func1" cannot be marked @final because it is not a method (reportGeneralTypeIssues)
+qualifiers_final_decorator.py:138:5 - error: Function "func1" cannot be marked @final because it is not a method (reportGeneralTypeIssues)
 """
-conformance_automated = "Pass"
+conformance_automated = "Fail"
 errors_diff = """
+Lines 86, 87: Expected error (tag 'method5')
 """
 ignore_errors = ["reportMissingModuleSource"]
diff --git a/conformance/results/pyright/version.toml b/conformance/results/pyright/version.toml
index e8e963b7..bd8e50c8 100644
--- a/conformance/results/pyright/version.toml
+++ b/conformance/results/pyright/version.toml
@@ -1,2 +1,2 @@
-version = "pyright 1.1.391"
-test_duration = 1.2
+version = "pyright 1.1.393"
+test_duration = 1.8
diff --git a/conformance/results/pytype/qualifiers_final_decorator.toml b/conformance/results/pytype/qualifiers_final_decorator.toml
index 3910ac78..16b45b10 100644
--- a/conformance/results/pytype/qualifiers_final_decorator.toml
+++ b/conformance/results/pytype/qualifiers_final_decorator.toml
@@ -21,7 +21,7 @@ qualifiers_final_decorator.py:52:16: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m
         return 0
                \u001b[1m\u001b[31m~\u001b[39m\u001b[0m
 
-qualifiers_final_decorator.py:55:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Class Derived2 overrides final method method4, defined in base class Base2 [final-error]
+qualifiers_final_decorator.py:63:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Class Derived2 overrides final method method5, defined in base class Base2 [final-error]
 
 class Derived2(Base2):
 \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
@@ -68,7 +68,15 @@ class Derived2(Base2):
         return 0
 \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
 
-qualifiers_final_decorator.py:55:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Class Derived2 overrides final method method3, defined in base class Base2 [final-error]
+\u001b[1m\u001b[31m\u001b[39m\u001b[0m
+    @property # E[method5]
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+    def method5(self) -> bool: # E[method5]
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+        return True
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+
+qualifiers_final_decorator.py:63:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Class Derived2 overrides final method method4, defined in base class Base2 [final-error]
 
 class Derived2(Base2):
 \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
@@ -115,7 +123,15 @@ class Derived2(Base2):
         return 0
 \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
 
-qualifiers_final_decorator.py:55:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Class Derived2 overrides final method method2, defined in base class Base2 [final-error]
+\u001b[1m\u001b[31m\u001b[39m\u001b[0m
+    @property # E[method5]
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+    def method5(self) -> bool: # E[method5]
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+        return True
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+
+qualifiers_final_decorator.py:63:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Class Derived2 overrides final method method3, defined in base class Base2 [final-error]
 
 class Derived2(Base2):
 \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
@@ -162,7 +178,15 @@ class Derived2(Base2):
         return 0
 \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
 
-qualifiers_final_decorator.py:55:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Class Derived2 overrides final method method1, defined in base class Base2 [final-error]
+\u001b[1m\u001b[31m\u001b[39m\u001b[0m
+    @property # E[method5]
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+    def method5(self) -> bool: # E[method5]
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+        return True
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+
+qualifiers_final_decorator.py:63:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Class Derived2 overrides final method method2, defined in base class Base2 [final-error]
 
 class Derived2(Base2):
 \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
@@ -209,22 +233,85 @@ class Derived2(Base2):
         return 0
 \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
 
-qualifiers_final_decorator.py:76:16: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in method4: bad return type [bad-return-type]
+\u001b[1m\u001b[31m\u001b[39m\u001b[0m
+    @property # E[method5]
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+    def method5(self) -> bool: # E[method5]
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+        return True
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+
+qualifiers_final_decorator.py:63:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Class Derived2 overrides final method method1, defined in base class Base2 [final-error]
+
+class Derived2(Base2):
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+    def method1(self) -> None:  # E
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+        pass
+\u001b[1m\u001b[31m~~~~~~~~~~~~\u001b[39m\u001b[0m
+
+\u001b[1m\u001b[31m\u001b[39m\u001b[0m
+    @classmethod  # E[method2]
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+    def method2(cls) -> None:  # E[method2]
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+        pass
+\u001b[1m\u001b[31m~~~~~~~~~~~~\u001b[39m\u001b[0m
+
+\u001b[1m\u001b[31m\u001b[39m\u001b[0m
+    @staticmethod  # E[method3]
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+    def method3() -> None:  # E[method3]
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+        pass
+\u001b[1m\u001b[31m~~~~~~~~~~~~\u001b[39m\u001b[0m
+
+\u001b[1m\u001b[31m\u001b[39m\u001b[0m
+    @overload  # E[method4]
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+    def method4(self, x: int) -> int:
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+        ...
+\u001b[1m\u001b[31m~~~~~~~~~~~\u001b[39m\u001b[0m
+
+\u001b[1m\u001b[31m\u001b[39m\u001b[0m
+    @overload
+\u001b[1m\u001b[31m~~~~~~~~~~~~~\u001b[39m\u001b[0m
+    def method4(self, x: str) -> str:
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+        ...
+\u001b[1m\u001b[31m~~~~~~~~~~~\u001b[39m\u001b[0m
+
+\u001b[1m\u001b[31m\u001b[39m\u001b[0m
+    def method4(self, x: int | str) -> int | str:  # E[method4]
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+        return 0
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+
+\u001b[1m\u001b[31m\u001b[39m\u001b[0m
+    @property # E[method5]
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+    def method5(self) -> bool: # E[method5]
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+        return True
+\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
+
+qualifiers_final_decorator.py:84:16: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in method4: bad return type [bad-return-type]
 
         return 0
                \u001b[1m\u001b[31m~\u001b[39m\u001b[0m
 
-qualifiers_final_decorator.py:90:16: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in method: bad return type [bad-return-type]
+qualifiers_final_decorator.py:102:16: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in method: bad return type [bad-return-type]
 
         return 0
                \u001b[1m\u001b[31m~\u001b[39m\u001b[0m
 
-qualifiers_final_decorator.py:103:16: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in method: bad return type [bad-return-type]
+qualifiers_final_decorator.py:115:16: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in method: bad return type [bad-return-type]
 
         return 0
                \u001b[1m\u001b[31m~\u001b[39m\u001b[0m
 
-qualifiers_final_decorator.py:117:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Class Derived5 overrides final method method, defined in base class Base5_2 [final-error]
+qualifiers_final_decorator.py:129:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Class Derived5 overrides final method method, defined in base class Base5_2 [final-error]
 
 class Derived5(Base5_1, Base5_2):
 \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
@@ -233,14 +320,14 @@ class Derived5(Base5_1, Base5_2):
         ...
 \u001b[1m\u001b[31m~~~~~~~~~~~\u001b[39m\u001b[0m
 
-qualifiers_final_decorator.py:118:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in Derived5: Overriding method signature mismatch [signature-mismatch]
+qualifiers_final_decorator.py:130:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in Derived5: Overriding method signature mismatch [signature-mismatch]
 
     def method(self) -> None:  # E
     \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
         ...
 \u001b[1m\u001b[31m~~~~~~~~~~~\u001b[39m\u001b[0m
 
-qualifiers_final_decorator.py:125:2: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Cannot apply @final decorator to func1 [final-error]
+qualifiers_final_decorator.py:137:2: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Cannot apply @final decorator to func1 [final-error]
 
 @final  # E[func]: not allowed on non-method function.
  \u001b[1m\u001b[31m~~~~~\u001b[39m\u001b[0m
@@ -248,18 +335,19 @@ qualifiers_final_decorator.py:125:2: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m
 """
 conformance_automated = "Fail"
 errors_diff = """
-Line 56: Expected 1 errors
-Lines 59, 60: Expected error (tag 'method2')
-Lines 63, 64: Expected error (tag 'method3')
-Lines 67, 75: Expected error (tag 'method4')
-Lines 80, 89: Expected error (tag 'Derived3')
-Lines 84, 85, 86: Expected error (tag 'Derived3-2')
-Lines 94, 102: Expected error (tag 'Derived4')
+Line 64: Expected 1 errors
+Lines 67, 68: Expected error (tag 'method2')
+Lines 71, 72: Expected error (tag 'method3')
+Lines 75, 83: Expected error (tag 'method4')
+Lines 86, 87: Expected error (tag 'method5')
+Lines 92, 101: Expected error (tag 'Derived3')
+Lines 96, 97, 98: Expected error (tag 'Derived3-2')
+Lines 106, 114: Expected error (tag 'Derived4')
 Line 8: Unexpected errors ["qualifiers_final_decorator.py:8:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Couldn't import pyi for '_qualifiers_final_decorator' [pyi-error]"]
 Line 52: Unexpected errors ['qualifiers_final_decorator.py:52:16: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in method4: bad return type [bad-return-type]']
-Line 55: Unexpected errors ['qualifiers_final_decorator.py:55:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Class Derived2 overrides final method method4, defined in base class Base2 [final-error]', 'qualifiers_final_decorator.py:55:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Class Derived2 overrides final method method3, defined in base class Base2 [final-error]', 'qualifiers_final_decorator.py:55:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Class Derived2 overrides final method method2, defined in base class Base2 [final-error]', 'qualifiers_final_decorator.py:55:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Class Derived2 overrides final method method1, defined in base class Base2 [final-error]']
-Line 76: Unexpected errors ['qualifiers_final_decorator.py:76:16: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in method4: bad return type [bad-return-type]']
-Line 90: Unexpected errors ['qualifiers_final_decorator.py:90:16: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in method: bad return type [bad-return-type]']
-Line 103: Unexpected errors ['qualifiers_final_decorator.py:103:16: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in method: bad return type [bad-return-type]']
-Line 117: Unexpected errors ['qualifiers_final_decorator.py:117:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Class Derived5 overrides final method method, defined in base class Base5_2 [final-error]']
+Line 63: Unexpected errors ['qualifiers_final_decorator.py:63:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Class Derived2 overrides final method method5, defined in base class Base2 [final-error]', 'qualifiers_final_decorator.py:63:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Class Derived2 overrides final method method4, defined in base class Base2 [final-error]', 'qualifiers_final_decorator.py:63:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Class Derived2 overrides final method method3, defined in base class Base2 [final-error]', 'qualifiers_final_decorator.py:63:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Class Derived2 overrides final method method2, defined in base class Base2 [final-error]', 'qualifiers_final_decorator.py:63:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Class Derived2 overrides final method method1, defined in base class Base2 [final-error]']
+Line 84: Unexpected errors ['qualifiers_final_decorator.py:84:16: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in method4: bad return type [bad-return-type]']
+Line 102: Unexpected errors ['qualifiers_final_decorator.py:102:16: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in method: bad return type [bad-return-type]']
+Line 115: Unexpected errors ['qualifiers_final_decorator.py:115:16: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in method: bad return type [bad-return-type]']
+Line 129: Unexpected errors ['qualifiers_final_decorator.py:129:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Class Derived5 overrides final method method, defined in base class Base5_2 [final-error]']
 """
diff --git a/conformance/results/pytype/version.toml b/conformance/results/pytype/version.toml
index 94cd5eee..e0712e9c 100644
--- a/conformance/results/pytype/version.toml
+++ b/conformance/results/pytype/version.toml
@@ -1,2 +1,2 @@
 version = "pytype 2024.10.11"
-test_duration = 37.2
+test_duration = 76.6
diff --git a/conformance/results/results.html b/conformance/results/results.html
index e388ee38..05364b19 100644
--- a/conformance/results/results.html
+++ b/conformance/results/results.html
@@ -158,17 +158,17 @@ <h3>Python Type System Conformance Test Results</h3>
         </header>
         <div class="table_container"><table><tbody>
 <tr><th class="col1">&nbsp;</th>
-<th class='tc-header'><div class='tc-name'>mypy 1.14.0</div>
-<div class='tc-time'>1.6sec</div>
+<th class='tc-header'><div class='tc-name'>mypy 1.14.1</div>
+<div class='tc-time'>3.3sec</div>
 </th>
-<th class='tc-header'><div class='tc-name'>pyright 1.1.391</div>
-<div class='tc-time'>1.2sec</div>
+<th class='tc-header'><div class='tc-name'>pyright 1.1.393</div>
+<div class='tc-time'>1.8sec</div>
 </th>
 <th class='tc-header'><div class='tc-name'>pyre 0.9.23</div>
-<div class='tc-time'>7.3sec</div>
+<div class='tc-time'>10.0sec</div>
 </th>
 <th class='tc-header'><div class='tc-name'>pytype 2024.10.11</div>
-<div class='tc-time'>37.2sec</div>
+<div class='tc-time'>76.6sec</div>
 </th>
 </tr>
 <tr><th class="column" colspan="5">
diff --git a/conformance/tests/qualifiers_final_decorator.py b/conformance/tests/qualifiers_final_decorator.py
index 3523ae53..88417505 100644
--- a/conformance/tests/qualifiers_final_decorator.py
+++ b/conformance/tests/qualifiers_final_decorator.py
@@ -51,6 +51,14 @@ def method4(self, x: str) -> str:
     def method4(self, x: int | str) -> int | str:
         return 0
 
+    # > @final may be chained with decorators that return a non-function, like a
+    # property descriptor.
+
+    @final
+    @property
+    def method5(self) -> int:
+        return 0
+
 
 class Derived2(Base2):
     def method1(self) -> None:  # E
@@ -75,6 +83,10 @@ def method4(self, x: str) -> str:
     def method4(self, x: int | str) -> int | str:  # E[method4]
         return 0
 
+    @property # E[method5]
+    def method5(self) -> bool: # E[method5]
+        return True
+
 
 class Derived3(Base3):
     @overload  # E[Derived3]

From 06ce4ccf766a20d6bde2618ed644539a04077958 Mon Sep 17 00:00:00 2001
From: Sam Goldman <samgoldman@meta.com>
Date: Thu, 30 Jan 2025 21:21:25 -0800
Subject: [PATCH 2/3] Add example of @final with @property to the typing spec

I thought it would be nice to add an example showing the use of @final
and @property together, but I also think the existing content is
reasonably clear that this example is supposed to work.
---
 docs/spec/qualifiers.rst | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/docs/spec/qualifiers.rst b/docs/spec/qualifiers.rst
index 7ba4d9f4..a4c00ebf 100644
--- a/docs/spec/qualifiers.rst
+++ b/docs/spec/qualifiers.rst
@@ -66,6 +66,22 @@ implementation (or on the first overload, for stubs)::
        def method(self, x=None):
            ...
 
+The ``@final`` decorator can be combined with previous decorators, like
+``@property``. Example::
+
+    from typing import final
+
+    class Base:
+        @final
+        @property
+        def foo(self) -> None:
+            ...
+
+    class Derived(Base):
+        @property
+        def foo(self) -> None:  # Error: Cannot override final attribute "foo"
+            ...
+
 It is an error to use ``@final`` on a non-method function.
 
 .. _`uppercase-final`:

From f4d1db668efaf156dee0cd9f13009d4b29838faf Mon Sep 17 00:00:00 2001
From: Sam Goldman <samgoldman@meta.com>
Date: Thu, 30 Jan 2025 21:49:48 -0800
Subject: [PATCH 3/3] Update conformance result for
 pyright/qualifiers_final_decorator.toml

---
 conformance/results/pyright/qualifiers_final_decorator.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/conformance/results/pyright/qualifiers_final_decorator.toml b/conformance/results/pyright/qualifiers_final_decorator.toml
index 11519dfa..ab5e3697 100644
--- a/conformance/results/pyright/qualifiers_final_decorator.toml
+++ b/conformance/results/pyright/qualifiers_final_decorator.toml
@@ -1,4 +1,4 @@
-conformant = "Pass"
+conformant = "Partial"
 output = """
 qualifiers_final_decorator.py:8:6 - warning: Import "_qualifiers_final_decorator" could not be resolved from source (reportMissingModuleSource)
 qualifiers_final_decorator.py:21:16 - error: Base class "Base1" is marked final and cannot be subclassed (reportGeneralTypeIssues)