Skip to content

Commit b1a32d8

Browse files
committed
[GR-35534] Backport to fix type constructor lookup
PullRequest: graalpython/2075
2 parents caa76e5 + 882aca3 commit b1a32d8

File tree

3 files changed

+74
-3
lines changed

3 files changed

+74
-3
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_class.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,72 @@ def test_new_not_descriptor():
5252
class C:
5353
__new__ = str
5454
assert C() == str(C)
55+
56+
57+
def test_meta_meta_new():
58+
class NewDescriptor():
59+
def new_descriptor_new(self):
60+
def m(*a, **kw):
61+
cls = type.__new__(*a, **kw)
62+
cls.metatype = NewDescriptor
63+
return cls
64+
return m
65+
66+
def __get__(self, *args):
67+
return self.new_descriptor_new()
68+
69+
def __set__(self, *args):
70+
raise NotImplementedError
71+
72+
class MetaMeta(type):
73+
def __new__(*args, **kwargs):
74+
cls = type.__new__(*args, **kwargs)
75+
cls.metatype = MetaMeta
76+
return cls
77+
78+
class Meta(type, metaclass=MetaMeta):
79+
def __new__(*args, **kwargs):
80+
cls = type.__new__(*args, **kwargs)
81+
cls.metatype = Meta
82+
return cls
83+
84+
assert Meta.metatype is MetaMeta
85+
86+
class aMeta(metaclass=Meta):
87+
pass
88+
89+
aMeta2 = type("aMeta2", (aMeta,), {})
90+
assert aMeta.metatype is Meta
91+
assert aMeta2.metatype is Meta
92+
93+
# overriding the meta-meta-class' __new__ does not affect creating new
94+
# instances of the meta-class
95+
MetaMeta.__new__ = Meta.__new__
96+
97+
class stillAMeta(metaclass=Meta):
98+
pass
99+
stillAMeta2 = type("stillAMeta2", (stillAMeta,), {})
100+
101+
# overriding the meta-meta-class' __new__ does affect creating new
102+
# meta-classes
103+
class aMetaThatIsNotAMetaMeta(metaclass=MetaMeta):
104+
pass
105+
aMetaThatIsNotAMetaMeta2 = type("aMetaThatIsNotAMetaMeta2", (aMetaThatIsNotAMetaMeta,), {})
106+
107+
assert stillAMeta.metatype is Meta
108+
assert stillAMeta2.metatype is Meta
109+
assert aMetaThatIsNotAMetaMeta.metatype is Meta
110+
assert aMetaThatIsNotAMetaMeta2.metatype is Meta
111+
112+
# setting the meta-meta class' __new__ to a data descriptor does affect
113+
# creating instances of the instances of the meta-meta-class
114+
MetaMeta.__new__ = NewDescriptor()
115+
116+
class notAMeta(metaclass=Meta):
117+
pass
118+
notAMeta2 = type("notAMeta2", (notAMeta,), {})
119+
120+
# the below assertions should pass, but this is such an unusual case that we
121+
# ignore this.
122+
# assert notAMeta.metatype is NewDescriptor
123+
# assert notAMeta2.metatype is NewDescriptor

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@
175175
import com.oracle.graal.python.builtins.objects.type.PythonManagedClass;
176176
import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot;
177177
import com.oracle.graal.python.builtins.objects.type.TypeFlags;
178+
import com.oracle.graal.python.builtins.objects.type.TypeBuiltins;
178179
import com.oracle.graal.python.builtins.objects.type.TypeNodes;
179180
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetBestBaseClassNode;
180181
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetItemsizeNode;
@@ -2140,7 +2141,8 @@ Object typeNew(VirtualFrame frame, Object cls, Object wName, PTuple bases, PDict
21402141
@Cached GetClassNode getClassNode,
21412142
@CachedLibrary(limit = "3") HashingStorageLibrary hashingStoragelib,
21422143
@Cached BranchProfile updatedStorage,
2143-
@Cached("create(New)") LookupInheritedSlotNode getNewFuncNode,
2144+
@Cached("create(New)") LookupCallableSlotInMRONode getNewFuncNode,
2145+
@Cached TypeBuiltins.BindNew bindNew,
21442146
@Cached("create(__INIT_SUBCLASS__)") GetAttributeNode getInitSubclassNode,
21452147
@Cached("create(SetName)") LookupInheritedSlotNode getSetNameNode,
21462148
@Cached("create(__MRO_ENTRIES__)") LookupInheritedAttributeNode lookupMroEntriesNode,
@@ -2167,7 +2169,7 @@ Object typeNew(VirtualFrame frame, Object cls, Object wName, PTuple bases, PDict
21672169
// the new metaclass has the same __new__ function as we are in, continue
21682170
} else {
21692171
// Pass it to the winner
2170-
return callNewFuncNode.execute(frame, newFunc, new Object[]{winner, name, bases, namespaceOrig}, kwds);
2172+
return callNewFuncNode.execute(frame, bindNew.execute(frame, newFunc, winner), new Object[]{winner, name, bases, namespaceOrig}, kwds);
21712173
}
21722174
}
21732175

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ Object selfSeparate(VirtualFrame frame, Object self, Object[] arguments, PKeywor
365365
}
366366

367367
@ReportPolymorphism
368-
protected abstract static class BindNew extends PNodeWithContext {
368+
public abstract static class BindNew extends PNodeWithContext {
369369
public abstract Object execute(VirtualFrame frame, Object descriptor, Object type);
370370

371371
@Specialization

0 commit comments

Comments
 (0)