@@ -1850,6 +1850,7 @@ static Object doPointer(GraalHPyContext hpyContext, PythonNativeObject n, @Suppr
1850
1850
* int basicsize;
1851
1851
* int itemsize;
1852
1852
* unsigned int flags;
1853
+ * int legacy;
1853
1854
* void *legacy_slots;
1854
1855
* HPyDef **defines;
1855
1856
* const char *doc;
@@ -1881,6 +1882,7 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
1881
1882
@ Cached HPyCreateGetSetDescriptorNode createGetSetDescriptorNode ,
1882
1883
@ Cached GetSuperClassNode getSuperClassNode ,
1883
1884
@ Cached IsSameTypeNode isSameTypeNode ,
1885
+ @ Cached ReadAttributeFromObjectNode readHPyTypeFlagsNode ,
1884
1886
@ Cached (parameters = "New" ) LookupCallableSlotInMRONode lookupNewNode ,
1885
1887
@ Cached HPyAsPythonObjectNode hPyAsPythonObjectNode ,
1886
1888
@ Cached PRaiseNode raiseNode ) {
@@ -1930,6 +1932,13 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
1930
1932
throw raiseNode .raise (TypeError , "HPy_TPFLAGS_INTERNAL_PURE should not be used directly, set .legacy=true instead" );
1931
1933
}
1932
1934
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
+
1933
1942
long basicSize = castToLong (valueLib , ptrLib .readMember (typeSpec , "basicsize" ));
1934
1943
long itemSize = castToLong (valueLib , ptrLib .readMember (typeSpec , "itemsize" ));
1935
1944
writeAttributeToObjectNode .execute (newType , GraalHPyDef .TYPE_HPY_ITEMSIZE , itemSize );
@@ -2007,10 +2016,10 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
2007
2016
* constructors won't usually do that. So, we compute the constructor here and
2008
2017
* decorate it.
2009
2018
*/
2019
+ Object baseClass = getSuperClassNode .execute (newType );
2010
2020
if (basicSize > 0 && !seenNew ) {
2011
2021
Object inheritedConstructor = null ;
2012
2022
2013
- Object baseClass = getSuperClassNode .execute (newType );
2014
2023
if (!isSameTypeNode .execute (baseClass , PythonBuiltinClassType .PythonObject )) {
2015
2024
// Lookup the inherited constructor and pass it to the HPy decorator.
2016
2025
inheritedConstructor = lookupNewNode .execute (baseClass );
@@ -2020,6 +2029,15 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
2020
2029
writeAttributeToObjectNode .execute (newType , SpecialMethodNames .__NEW__ , constructorDecorator );
2021
2030
}
2022
2031
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
+
2023
2041
return newType ;
2024
2042
} catch (CannotCastException | InteropException e ) {
2025
2043
throw raiseNode .raise (SystemError , "Could not create type from spec because: %m" , e );
@@ -2100,6 +2118,24 @@ private static String[] splitName(String specName) {
2100
2118
return new String []{null , specName };
2101
2119
}
2102
2120
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
+
2103
2139
private static long castToLong (InteropLibrary lib , Object value ) throws OverflowException {
2104
2140
if (lib .fitsInLong (value )) {
2105
2141
try {
0 commit comments