Skip to content

Commit 0e3b88e

Browse files
committed
Adding check for non-final class and method returning Self
1 parent 5f38878 commit 0e3b88e

File tree

3 files changed

+17
-1
lines changed

3 files changed

+17
-1
lines changed

pyrefly/lib/solver/subset.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1004,7 +1004,8 @@ impl<'a, Ans: LookupAnswer> Subset<'a, Ans> {
10041004
}
10051005
(Type::ClassType(got), Type::SelfType(want)) => ok_or(
10061006
self.type_order
1007-
.has_superclass(got.class_object(), want.class_object()),
1007+
.has_superclass(got.class_object(), want.class_object())
1008+
&& self.type_order.is_final(want.class_object()),
10081009
SubsetError::Other,
10091010
),
10101011
(Type::Type(box Type::ClassType(got)), Type::SelfType(want)) => ok_or(

pyrefly/lib/solver/type_order.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ impl<'a, Ans: LookupAnswer> TypeOrder<'a, Ans> {
8585
self.0.get_metadata_for_class(cls).is_new_type()
8686
}
8787

88+
pub fn is_final(self, cls: &Class) -> bool {
89+
self.0.get_metadata_for_class(cls).is_final()
90+
}
91+
8892
pub fn get_protocol_member_names(self, cls: &Class) -> SmallSet<Name> {
8993
let meta = self.0.get_metadata_for_class(cls);
9094
if let Some(proto) = meta.protocol_metadata() {

pyrefly/lib/test/simple.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1785,3 +1785,14 @@ X = type("X", (object,), {"foo": "bar"}) # E: No matching overload
17851785
assert_type(X, type) # E: assert_type(Any, type)
17861786
"#,
17871787
);
1788+
1789+
testcase!(
1790+
test_nonfinal_class_self_return_type,
1791+
r#"
1792+
from typing import Self
1793+
1794+
class NonFinalClass:
1795+
def test(self) -> Self:
1796+
return NonFinalClass() # E: Returned type `NonFinalClass` is not assignable to declared return type `Self@NonFinalClass`
1797+
"#,
1798+
);

0 commit comments

Comments
 (0)