11/*
2- * Copyright (c) 2024, 2024 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2024, 2025 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * The Universal Permissive License (UPL), Version 1.0
6363import javax .tools .Diagnostic .Kind ;
6464import javax .tools .JavaFileObject ;
6565
66+ import com .oracle .graal .python .annotations .HashNotImplemented ;
6667import com .oracle .graal .python .annotations .Slot ;
6768import com .oracle .graal .python .annotations .Slot .SlotKind ;
6869import com .oracle .graal .python .annotations .Slot .Slots ;
@@ -72,11 +73,27 @@ public class SlotsProcessor extends AbstractProcessor {
7273 private static final boolean LOGGING = false ;
7374
7475 public record TpSlotData (Slot slot , TypeElement enclosingType , TypeElement slotNodeType ) {
76+ public boolean isHashNotImplemented () {
77+ return slotNodeType == null ;
78+ }
79+
80+ public static TpSlotData createHashNotImplemented (TypeElement enclosingType ) {
81+ return new TpSlotData (null , enclosingType , null );
82+ }
83+
84+ public String builderCall () {
85+ if (isHashNotImplemented ()) {
86+ return ".set(TpSlots.TpSlotMeta.TP_HASH, com.oracle.graal.python.builtins.objects.type.slots.TpSlotHashFun.HASH_NOT_IMPLEMENTED)" ;
87+ }
88+ return String .format (".set(TpSlots.TpSlotMeta.%s, %s.INSTANCE)" , //
89+ slot .value ().name ().toUpperCase (Locale .ROOT ), //
90+ getSlotImplName (slot .value ()));
91+ }
7592 }
7693
7794 @ Override
7895 public Set <String > getSupportedAnnotationTypes () {
79- return Set .of (Slot .class .getName ());
96+ return Set .of (Slot .class .getName (), HashNotImplemented . class . getName () );
8097 }
8198
8299 @ Override
@@ -109,7 +126,14 @@ private void doProcess(RoundEnvironment roundEnv) throws IOException, Processing
109126 private void validate (HashMap <TypeElement , Set <TpSlotData >> enclosingTypes ) throws ProcessingError {
110127 var typeCache = new TypeCache (processingEnv );
111128 for (Entry <TypeElement , Set <TpSlotData >> enclosingType : enclosingTypes .entrySet ()) {
129+ boolean seenHashNotImplemented = false ;
130+ boolean seenHash = false ;
112131 for (TpSlotData slot : enclosingType .getValue ()) {
132+ if (slot .isHashNotImplemented ()) {
133+ seenHashNotImplemented = true ;
134+ continue ;
135+ }
136+ seenHash |= slot .slot .value () == SlotKind .tp_hash ;
113137 if (slot .slot .isComplex ()) {
114138 if (!SlotsMapping .supportsComplex (slot .slot ().value ())) {
115139 throw error (slot .slotNodeType , "Slot does not support complex builtins. The support can be added." );
@@ -125,14 +149,22 @@ private void validate(HashMap<TypeElement, Set<TpSlotData>> enclosingTypes) thro
125149 throw error (slot .slotNodeType , "Slot does not inherit from expected base class '%s'" , baseName );
126150 }
127151 }
152+ if (seenHash && seenHashNotImplemented ) {
153+ throw error (enclosingType .getKey (), "Annotation %s cannot be use when there is also %s(tp_hash). Remove one or the other." ,
154+ HashNotImplemented .class .getSimpleName (),
155+ Slot .class .getSimpleName ());
156+ }
128157 }
129158 }
130159
131160 @ SuppressWarnings ("try" )
132161 private void writeCode (HashMap <TypeElement , Set <TpSlotData >> enclosingTypes ) throws IOException {
133- for (Entry <TypeElement , Set <TpSlotData >> enclosingType : enclosingTypes .entrySet ()) {
134- String pkgName = getPackage (enclosingType .getKey ());
135- String className = enclosingType .getKey ().getSimpleName () + "SlotsGen" ;
162+ for (Entry <TypeElement , Set <TpSlotData >> enclosingTypeAndSlots : enclosingTypes .entrySet ()) {
163+ Set <TpSlotData > slots = enclosingTypeAndSlots .getValue ();
164+ TypeElement enclosingType = enclosingTypeAndSlots .getKey ();
165+
166+ String pkgName = getPackage (enclosingType );
167+ String className = enclosingType .getSimpleName () + "SlotsGen" ;
136168 String sourceFile = pkgName + "." + className ;
137169 log ("Generating file '%s'" , sourceFile );
138170
@@ -146,10 +178,10 @@ private void writeCode(HashMap<TypeElement, Set<TpSlotData>> enclosingTypes) thr
146178 w .writeLn ();
147179 w .writeLn ("public class %s {" , className );
148180 try (Block i = w .newIndent ()) {
149- for (TpSlotData slot : enclosingType . getValue () ) {
181+ for (TpSlotData slot : slots ) {
150182 writeSlot (w , slot );
151183 }
152- writeSlotsStaticField (w , enclosingType . getValue () );
184+ writeSlotsStaticField (w , enclosingType , slots );
153185 }
154186 w .writeLn ("}" );
155187 }
@@ -168,6 +200,9 @@ private void writeImports(CodeWriter w) throws IOException {
168200
169201 @ SuppressWarnings ("try" )
170202 private void writeSlot (CodeWriter w , TpSlotData slot ) throws IOException {
203+ if (slot .isHashNotImplemented ()) {
204+ return ;
205+ }
171206 log ("Writing slot node %s" , slot .slotNodeType );
172207 String slotImplName = getSlotImplName (slot .slot .value ());
173208 String genericArg = "" ;
@@ -202,13 +237,11 @@ private void writeSlot(CodeWriter w, TpSlotData slot) throws IOException {
202237 }
203238
204239 @ SuppressWarnings ("try" )
205- private static void writeSlotsStaticField (CodeWriter w , Set <TpSlotData > slots ) throws IOException {
240+ private static void writeSlotsStaticField (CodeWriter w , TypeElement enclosingType , Set <TpSlotData > slots ) throws IOException {
206241 w .writeLn ("static final TpSlots SLOTS = TpSlots.newBuilder()" );
207242 try (Block i3 = w .newIndent ()) {
208243 String defs = slots .stream ().//
209- map (s -> String .format (".set(TpSlots.TpSlotMeta.%s, %s.INSTANCE)" , //
210- s .slot .value ().name ().toUpperCase (Locale .ROOT ), //
211- getSlotImplName (s .slot .value ()))).//
244+ map (TpSlotData ::builderCall ).//
212245 collect (Collectors .joining ("\n " ));
213246 w .writeLn ("%s." , defs );
214247 w .writeLn ("build();" );
@@ -237,6 +270,12 @@ private HashMap<TypeElement, Set<TpSlotData>> collectEnclosingTypes(RoundEnviron
237270 tpSlotDataSet .add (new TpSlotData (slotAnnotation , enclosingType , type ));
238271 }
239272 }
273+ elements = new HashSet <>(roundEnv .getElementsAnnotatedWithAny (Set .of (HashNotImplemented .class )));
274+ for (Element element : elements ) {
275+ TypeElement typeElement = (TypeElement ) element ;
276+ enclosingTypes .computeIfAbsent (typeElement , key -> new HashSet <>()).//
277+ add (TpSlotData .createHashNotImplemented (typeElement ));
278+ }
240279 return enclosingTypes ;
241280 }
242281
0 commit comments