@@ -24,6 +24,9 @@ public class EliminateGenerics {
2424 private final Table <ImClass , GenericTypes , ImClass > specializedClasses = HashBasedTable .create ();
2525 private final Multimap <ImClass , BiConsumer <GenericTypes , ImClass >> onSpecializedClassTriggers = HashMultimap .create ();
2626
27+ // Track concrete generic arguments for specialized functions to simplify later lookups
28+ private final Map <ImFunction , GenericTypes > specializedFunctionGenerics = new IdentityHashMap <>();
29+
2730 // NEW: Track specialized global variables for generic static fields
2831 // Key: (original generic global var, concrete type instantiation) -> specialized var
2932 private final Table <ImVar , GenericTypes , ImVar > specializedGlobals = HashBasedTable .create ();
@@ -205,15 +208,6 @@ private void removeGenericConstructs() {
205208 for (ImClass c : prog .getClasses ()) {
206209 c .getFields ().removeIf (f -> isGenericType (f .getType ()));
207210 }
208-
209- // NEW: Remove original generic global variables
210- prog .getGlobals ().removeIf (v -> {
211- if (globalToClass .containsKey (v )) {
212- WLogger .info ("Removing generic global variable: " + v .getName () + " with type " + v .getType ());
213- return true ;
214- }
215- return false ;
216- });
217211 }
218212
219213 private void eliminateGenericUses () {
@@ -283,6 +277,7 @@ private ImFunction specializeFunction(ImFunction f, GenericTypes generics) {
283277
284278 ImFunction newF = f .copyWithRefs ();
285279 specializedFunctions .put (f , generics , newF );
280+ specializedFunctionGenerics .put (newF , generics );
286281 prog .getFunctions ().add (newF );
287282 newF .getTypeVariables ().removeAll ();
288283 List <ImTypeVar > typeVars = f .getTypeVariables ();
@@ -442,7 +437,7 @@ private ImClass specializeClass(ImClass c, GenericTypes generics) {
442437 return specialized ;
443438 }
444439 if (generics .containsTypeVariable ()) {
445- throw new CompileError (c , "Generics should not contain type variables." );
440+ throw new CompileError (c , "Generics should not contain type variables (" + c . getName () + " ⟪" + generics . makeName () + "⟫) ." );
446441 }
447442 ImClass newC = c .copyWithRefs ();
448443 newC .setSuperClasses (new ArrayList <>(newC .getSuperClasses ()));
@@ -816,6 +811,22 @@ public void eliminate() {
816811 ImVar f = ma .getVar ();
817812 ImClass owningClass = (ImClass ) f .getParent ().getParent ();
818813 GenericTypes generics = new GenericTypes (specializeTypeArgs (ma .getTypeArguments ()));
814+ // If the access still carries type variables, defer specialization until a concrete
815+ // instantiation is created (e.g. when the surrounding generic function/class is
816+ // specialized). If the receiver type is already concrete we can directly resolve the
817+ // target field using that type information.
818+ if (generics .containsTypeVariable ()) {
819+ ImType receiverType = specializeType (ma .getReceiver ().attrTyp ());
820+ if (receiverType instanceof ImClassType ) {
821+ ImClass specializedClass = ((ImClassType ) receiverType ).getClassDef ();
822+ int fieldIndex = owningClass .getFields ().indexOf (f );
823+ ImVar newVar = specializedClass .getFields ().get (fieldIndex );
824+ ma .setVar (newVar );
825+ ma .getTypeArguments ().removeAll ();
826+ newVar .setType (specializeType (newVar .getType ()));
827+ }
828+ return ;
829+ }
819830 ImClass specializedClass = specializeClass (owningClass , generics );
820831 int fieldIndex = owningClass .getFields ().indexOf (f );
821832 ImVar newVar = specializedClass .getFields ().get (fieldIndex );
@@ -925,6 +936,11 @@ private GenericTypes inferGenericsFromFunction(Element element, ImClass owningCl
925936 if (current instanceof ImFunction ) {
926937 ImFunction func = (ImFunction ) current ;
927938
939+ GenericTypes specialized = specializedFunctionGenerics .get (func );
940+ if (specialized != null ) {
941+ return specialized ;
942+ }
943+
928944 // If function is still generic, we can't decide yet.
929945 if (!func .getTypeVariables ().isEmpty ()) {
930946 return null ;
@@ -1073,7 +1089,22 @@ private ImType specializeType(ImType type) {
10731089 public ImType case_ImClassType (ImClassType t ) {
10741090 ImTypeArguments typeArgs = t .getTypeArguments ();
10751091 List <ImTypeArgument > newTypeArgs = specializeTypeArgs (typeArgs );
1076- ImClass specializedClass = specializeClass (t .getClassDef (), new GenericTypes (newTypeArgs ));
1092+ GenericTypes generics = new GenericTypes (newTypeArgs );
1093+
1094+ if (generics .containsTypeVariable ()) {
1095+ Map <GenericTypes , ImClass > specialized = specializedClasses .row (t .getClassDef ());
1096+
1097+ if (!specialized .isEmpty ()) {
1098+ ImClass firstSpecialization = specialized .values ().iterator ().next ();
1099+ return JassIm .ImClassType (firstSpecialization , JassIm .ImTypeArguments ());
1100+ }
1101+
1102+ ImTypeArguments copiedArgs = JassIm .ImTypeArguments ();
1103+ copiedArgs .addAll (newTypeArgs );
1104+ return JassIm .ImClassType (t .getClassDef (), copiedArgs );
1105+ }
1106+
1107+ ImClass specializedClass = specializeClass (t .getClassDef (), generics );
10771108 return JassIm .ImClassType (specializedClass , JassIm .ImTypeArguments ());
10781109 }
10791110
@@ -1099,7 +1130,27 @@ class GenericReturnTypeFunc implements GenericUse {
10991130
11001131 @ Override
11011132 public void eliminate () {
1102- mc .setReturnType (specializeType (mc .getReturnType ()));
1133+ ImType returnType = mc .getReturnType ();
1134+
1135+ if (containsTypeVariable (returnType ) && returnType instanceof ImClassType && !mc .getParameters ().isEmpty ()) {
1136+ ImClassType retClassType = (ImClassType ) returnType ;
1137+ ImType receiverType = mc .getParameters ().get (0 ).getType ();
1138+
1139+ if (receiverType instanceof ImClassType ) {
1140+ ImClassType receiverClassType = (ImClassType ) receiverType ;
1141+ ImClassType adapted = adaptToSuperclass (receiverClassType , retClassType .getClassDef ());
1142+
1143+ if (adapted != null ) {
1144+ GenericTypes concrete = new GenericTypes (specializeTypeArgs (adapted .getTypeArguments ()));
1145+ ImType specialized = ImAttrType .substituteType (returnType , concrete .getTypeArguments (), retClassType .getClassDef ().getTypeVariables ());
1146+
1147+ mc .setReturnType (specializeType (specialized ));
1148+ return ;
1149+ }
1150+ }
1151+ }
1152+
1153+ mc .setReturnType (specializeType (returnType ));
11031154 }
11041155 }
11051156
0 commit comments