From 5c088f0eb4af03856899d505582d7069e50c418b Mon Sep 17 00:00:00 2001 From: vaggelisd Date: Fri, 27 Feb 2026 14:57:51 +0200 Subject: [PATCH] Fix vtable construction for deep trait inheritance --- mypyc/irbuild/vtable.py | 2 +- mypyc/test-data/run-classes.test | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/mypyc/irbuild/vtable.py b/mypyc/irbuild/vtable.py index 2d4f7261e4ca6..0aa699626525f 100644 --- a/mypyc/irbuild/vtable.py +++ b/mypyc/irbuild/vtable.py @@ -37,7 +37,7 @@ def compute_vtable(cls: ClassIR) -> None: all_traits = [t for t in cls.mro if t.is_trait] - for t in [cls] + cls.traits: + for t in [cls] + [t for t in all_traits if t is not cls]: for fn in itertools.chain(t.methods.values()): # TODO: don't generate a new entry when we overload without changing the type if fn == cls.get_method(fn.name, prefer_method=True): diff --git a/mypyc/test-data/run-classes.test b/mypyc/test-data/run-classes.test index cd3a0bf349b71..2c982e5b0a8e7 100644 --- a/mypyc/test-data/run-classes.test +++ b/mypyc/test-data/run-classes.test @@ -5676,3 +5676,33 @@ def test_derived_acyclic() -> None: assert d.x == 3 assert d.y == "hi" assert not gc.is_tracked(d) + +[case testTraitVtableGrandparentMethod] +from typing import Any +from mypy_extensions import trait, mypyc_attr + +@mypyc_attr(allow_interpreted_subclasses=True) +@trait +class Base: + def value(self) -> Any: + return 42 + +@mypyc_attr(allow_interpreted_subclasses=True) +@trait +class Middle(Base): + pass + +@mypyc_attr(allow_interpreted_subclasses=True) +@trait +class Child(Middle): + def derived(self) -> Any: + return self.value() + +class Concrete(Child): + pass + +[file driver.py] +from native import Concrete +c = Concrete() +assert c.value() == 42 +assert c.derived() == 42