From bca558add8c8e1a0d5abfa9a377ee105be648d4e Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Sat, 18 Jul 2026 11:23:47 +0900 Subject: [PATCH] fix --- pyrefly/lib/alt/class/class_metadata.rs | 24 +++++++++++++++++------- pyrefly/lib/test/class_keywords.rs | 14 ++++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/pyrefly/lib/alt/class/class_metadata.rs b/pyrefly/lib/alt/class/class_metadata.rs index 3d9480d115..45ecc9ef1a 100644 --- a/pyrefly/lib/alt/class/class_metadata.rs +++ b/pyrefly/lib/alt/class/class_metadata.rs @@ -9,6 +9,7 @@ use std::iter; use std::sync::Arc; use dupe::Dupe; +use dupe::IterDupedExt; use itertools::Either; use itertools::Itertools; use pyrefly_graph::index::Idx; @@ -2072,13 +2073,22 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> { /// Check if `metaclass_cls` is `abc.ABCMeta` or has `abc.ABCMeta` anywhere in its /// inheritance chain. fn metaclass_extends_abcmeta(&self, metaclass_cls: &Class) -> bool { - if metaclass_cls.has_toplevel_qname("abc", "ABCMeta") { - return true; + let mut pending = vec![metaclass_cls.dupe()]; + let mut seen = SmallSet::new(); + while let Some(cls) = pending.pop() { + if !seen.insert(cls.dupe()) { + continue; + } + if cls.has_toplevel_qname("abc", "ABCMeta") { + return true; + } + pending.extend( + self.get_metadata_for_class(&cls) + .base_class_objects() + .iter() + .duped(), + ); } - let metadata = self.get_metadata_for_class(metaclass_cls); - metadata - .base_class_objects() - .iter() - .any(|base| self.metaclass_extends_abcmeta(base)) + false } } diff --git a/pyrefly/lib/test/class_keywords.rs b/pyrefly/lib/test/class_keywords.rs index d34757e694..946e37ab60 100644 --- a/pyrefly/lib/test/class_keywords.rs +++ b/pyrefly/lib/test/class_keywords.rs @@ -154,6 +154,20 @@ f(C2[int]) "#, ); +testcase!( + test_recursive_base_used_as_metaclass, + r#" +class C(C): # E: Class `C` inheriting from `C` creates a cycle + pass + +class D(C, _): # E: Class `D` inheriting from `C` creates a cycle # E: Could not find name `_` + pass + +class E(metaclass=D): + pass +"#, +); + testcase!( test_illegal_unpacking, r#"