Skip to content

Commit ad28863

Browse files
committed
Fix HPy test test_legacy_inherits_from_pure_raises
1 parent 1050f7d commit ad28863

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/hpy/GraalHPyNodes.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1850,6 +1850,7 @@ static Object doPointer(GraalHPyContext hpyContext, PythonNativeObject n, @Suppr
18501850
* int basicsize;
18511851
* int itemsize;
18521852
* unsigned int flags;
1853+
* int legacy;
18531854
* void *legacy_slots;
18541855
* HPyDef **defines;
18551856
* const char *doc;
@@ -1881,6 +1882,7 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
18811882
@Cached HPyCreateGetSetDescriptorNode createGetSetDescriptorNode,
18821883
@Cached GetSuperClassNode getSuperClassNode,
18831884
@Cached IsSameTypeNode isSameTypeNode,
1885+
@Cached ReadAttributeFromObjectNode readHPyTypeFlagsNode,
18841886
@Cached(parameters = "New") LookupCallableSlotInMRONode lookupNewNode,
18851887
@Cached HPyAsPythonObjectNode hPyAsPythonObjectNode,
18861888
@Cached PRaiseNode raiseNode) {
@@ -1930,6 +1932,13 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
19301932
throw raiseNode.raise(TypeError, "HPy_TPFLAGS_INTERNAL_PURE should not be used directly, set .legacy=true instead");
19311933
}
19321934

1935+
long legacy = castToLong(valueLib, ptrLib.readMember(typeSpec, "legacy"));
1936+
if (legacy != 0) {
1937+
flags &= ~GraalHPyDef.HPy_TPFLAGS_INTERNAL_PURE;
1938+
} else {
1939+
flags |= GraalHPyDef.HPy_TPFLAGS_INTERNAL_PURE;
1940+
}
1941+
19331942
long basicSize = castToLong(valueLib, ptrLib.readMember(typeSpec, "basicsize"));
19341943
long itemSize = castToLong(valueLib, ptrLib.readMember(typeSpec, "itemsize"));
19351944
writeAttributeToObjectNode.execute(newType, GraalHPyDef.TYPE_HPY_ITEMSIZE, itemSize);
@@ -2007,10 +2016,10 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
20072016
* constructors won't usually do that. So, we compute the constructor here and
20082017
* decorate it.
20092018
*/
2019+
Object baseClass = getSuperClassNode.execute(newType);
20102020
if (basicSize > 0 && !seenNew) {
20112021
Object inheritedConstructor = null;
20122022

2013-
Object baseClass = getSuperClassNode.execute(newType);
20142023
if (!isSameTypeNode.execute(baseClass, PythonBuiltinClassType.PythonObject)) {
20152024
// Lookup the inherited constructor and pass it to the HPy decorator.
20162025
inheritedConstructor = lookupNewNode.execute(baseClass);
@@ -2020,6 +2029,15 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
20202029
writeAttributeToObjectNode.execute(newType, SpecialMethodNames.__NEW__, constructorDecorator);
20212030
}
20222031

2032+
long baseFlags;
2033+
if (baseClass instanceof PythonClass) {
2034+
baseFlags = ((PythonClass) baseClass).flags;
2035+
} else {
2036+
Object baseFlagsObj = readHPyTypeFlagsNode.execute(baseClass, GraalHPyDef.TYPE_HPY_FLAGS);
2037+
baseFlags = baseFlagsObj != PNone.NO_VALUE ? (long) baseFlagsObj : 0;
2038+
}
2039+
checkInheritanceConstraints(flags, baseFlags, raiseNode);
2040+
20232041
return newType;
20242042
} catch (CannotCastException | InteropException e) {
20252043
throw raiseNode.raise(SystemError, "Could not create type from spec because: %m", e);
@@ -2100,6 +2118,24 @@ private static String[] splitName(String specName) {
21002118
return new String[]{null, specName};
21012119
}
21022120

2121+
private static void checkInheritanceConstraints(long flags, long baseFlags, PRaiseNode raiseNode) {
2122+
boolean isPure = (flags & GraalHPyDef.HPy_TPFLAGS_INTERNAL_PURE) != 0;
2123+
boolean isBasePure = (baseFlags & GraalHPyDef.HPy_TPFLAGS_INTERNAL_PURE) != 0;
2124+
// Pure types may inherit from:
2125+
//
2126+
// * pure types, or
2127+
// * PyBaseObject_Type, or
2128+
// * other builtin or legacy types as long as long as they do not
2129+
// access the struct layout (e.g. by using HPy_AsStruct or defining
2130+
// a deallocator with HPy_tp_destroy).
2131+
//
2132+
// It would be nice to relax these restrictions or check them here.
2133+
// See https://github.com/hpyproject/hpy/issues/169 for details.
2134+
if (!isPure && isBasePure) {
2135+
throw raiseNode.raise(TypeError, "A legacy type should not inherit its memory layout from a pure type");
2136+
}
2137+
}
2138+
21032139
private static long castToLong(InteropLibrary lib, Object value) throws OverflowException {
21042140
if (lib.fitsInLong(value)) {
21052141
try {

graalpython/lib-graalpython/modules/hpy/test/test_hpytype_legacy.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ def test_legacy_methods(self):
103103
assert mod.h(4, 5, 6) == 456
104104
assert mod.k(c=6, b=5, a=4) == 456
105105

106-
@pytest.mark.xfail
107106
def test_legacy_inherits_from_pure_raises(self):
108107
import pytest
109108
mod_src = """

0 commit comments

Comments
 (0)