Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 29
Stop composing a dispatch slot which names no method#1247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
5970878dea459b2d15413137edc1File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -8,6 +8,7 @@ | ||
| import de.peeeq.wurstscript.translation.imtranslation.GetAForB; | ||
| import de.peeeq.wurstscript.translation.imtranslation.ImHelper; | ||
| import de.peeeq.wurstscript.translation.imtranslation.ImTranslator; | ||
| import de.peeeq.wurstscript.translation.imtranslation.LuaDispatchPreparation; | ||
| import de.peeeq.wurstscript.translation.imtranslation.LuaNativeLowering; | ||
| import de.peeeq.wurstscript.types.TypesHelper; | ||
| import de.peeeq.wurstscript.utils.Lazy; | ||
| @@ -1029,17 +1030,71 @@ private Set<String> collectDispatchSlotNames(ImClass receiverClass, List<ImMetho | ||
| } | ||
| } | ||
| if (receiverClass != null && !semanticNames.isEmpty()) { | ||
| // A semantic name which several of the class's methods share names none of them, so a | ||
| // slot composed from it would be claimed by whichever is bound first. For a specialised | ||
| // class every method's trailing segment is the type argument, which is exactly that | ||
| // case, and the resulting slot is never called. Left uncomposed rather than bound | ||
| // arbitrarily; LuaDispatchPreparation drops the matching alias for the same reason. | ||
| Set<String> ambiguous = ambiguousSemanticNames(receiverClass); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For a class with M dispatch groups, AGENTS.md reference: AGENTS.md:L88-L91 Useful? React with 👍 / 👎. | ||
| Set<String> classNames = new TreeSet<>(); | ||
| collectClassNamesInHierarchy(receiverClass, classNames, new HashSet<>()); | ||
| for (String className : classNames) { | ||
| for (String semanticName : semanticNames) { | ||
| if (ambiguous.contains(semanticName)) { | ||
| continue; | ||
| } | ||
| slotNames.add(dispatchSlotName(className + "_" + semanticName)); | ||
| } | ||
| } | ||
| } | ||
| return slotNames; | ||
| } | ||
| /** | ||
| * The semantic names which name no method in particular, cached per class. | ||
| * <p> | ||
| * A method and its overrides share a semantic name and must share a slot: that is dispatch, and | ||
| * they all declare the same name in the source. The siblings of one specialisation declare | ||
| * different names and still compose the same segment, because for a specialised method that | ||
| * segment is the type argument - and the slot composed from it is claimed by whichever is bound | ||
| * first, then never called. | ||
| * <p> | ||
| * The dispatch group key would be a sharper identity but cannot be used: it embeds the signature, | ||
| * and a generic override chain's signatures differ by the type variable of each class in it | ||
| * ({@code void|T192,real} against {@code void|T636,real}), so overrides would read as unrelated | ||
| * and their shared slot would be dropped. What that leaves uncovered is recorded in backlog | ||
| * item 15: overloads of one source method inside a specialised class share a declared name, so | ||
| * their composed name is not seen as ambiguous and one dead key survives there. | ||
| * <p> | ||
| * Cached because {@code createMethods} asks twice per dispatch group and each ask would otherwise | ||
| * rebuild and sort the whole inherited method list. | ||
| */ | ||
| private final Map<ImClass, Set<String>> ambiguousSemanticNamesByClass = new LinkedHashMap<>(); | ||
| private Set<String> ambiguousSemanticNames(ImClass c) { | ||
| return ambiguousSemanticNamesByClass.computeIfAbsent(c, owner -> { | ||
| Map<String, Set<String>> claimants = new TreeMap<>(); | ||
| for (ImMethod m : collectMethodsInHierarchy(owner)) { | ||
| if (m == null) { | ||
| continue; | ||
| } | ||
| String semanticName = semanticNameFromMethodName(m.getName()); | ||
| if (semanticName.isEmpty()) { | ||
| continue; | ||
| } | ||
| claimants.computeIfAbsent(semanticName, name -> new TreeSet<>()) | ||
| .add(LuaDispatchPreparation.declaredName(m)); | ||
| } | ||
| Set<String> ambiguous = new TreeSet<>(); | ||
| claimants.forEach((name, keys) -> { | ||
| if (keys.size() > 1) { | ||
| ambiguous.add(name); | ||
| } | ||
| }); | ||
| return ambiguous; | ||
| }); | ||
| } | ||
| private void collectClassNamesInHierarchy(ImClass c, Set<String> out, Set<ImClass> visited) { | ||
| if (c == null || !visited.add(c)) { | ||
| return; | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a specialized generic class contains multiple overloads of the same source method and no differently named method sharing the suffix, every specialized IM method can compose the same type-argument alias while
declaredName(method)is identical for all overloads. The alias is therefore never marked ambiguous, so both composers retain the arbitrary junk slot this change intends to remove; the FastHashMap test misses this because its methods have distinct declared names. Include overload/group identity in this collision case without separating actual override chains.Useful? React with 👍 / 👎.