Methodenaufruf beim Aufruf überladener Methoden teilweise falsch #332

Open
opened 2024-05-13 17:52:04 +00:00 by i21023 · 9 comments
Collaborator

Es gab den gleichen Bug schon einmal #307, inzwischen tritt er allerdings nur noch auf, wenn ich Java und Jav Dateien mixe. Zumindest hab ich den alten Bug #307 jetzt einige male ausprobiert und er ist nicht aufgetreten. Aber da der Bug nur manchmal auftritt habe ich vielleicht einfach nicht lange genug getestet.

Der Testaufbau ist ein bisschen umständlich, da es zirkuläre Imports zwischen den Java und Jav Dateien gibt.

Daher muss die Jav Datei zusätzlich auch als Java Datei vorliegen, damit man es initial compilerbar ist.

Ich habe die notwendigen Dateien in den Anhang geladen.
Auf einem unixoiden System sollte mit dem folgenden Befehl der Test automatisiert werden können. Also zip entpacken, in den Ordner gehen und Befehl ausführen.

rm -f *.class && javac Main.java && java -jar JavaTXCompiler.jar Foo.jav && java Main

Achtung, es sollten keine anderen Class Dateien im aktuellen Ordner liegen, sonst werden diese gelöscht!

Die Ausgabe des Befehls variiert wenn man ihn öfter ausführt. Die korrekte Ausgabe wäre "Foo", es wird aber teilweise auch "Object" ausgegeben. Also irgendetwas stimmt wohl in der Typinferenz nicht.

TxGenerics Foo: []
JavaGenerics Foo: []
TxGenerics Foo: []
generating Foo.class file ...
Foo.class
Foo.class file generated
Foo
TxGenerics Foo: []
JavaGenerics Foo: []
TxGenerics Foo: []
generating Foo.class file ...
Foo.class
Foo.class file generated
Object
Es gab den gleichen Bug schon einmal #307, inzwischen tritt er allerdings nur noch auf, wenn ich Java und Jav Dateien mixe. Zumindest hab ich den alten Bug #307 jetzt einige male ausprobiert und er ist nicht aufgetreten. Aber da der Bug nur manchmal auftritt habe ich vielleicht einfach nicht lange genug getestet. Der Testaufbau ist ein bisschen umständlich, da es zirkuläre Imports zwischen den Java und Jav Dateien gibt. Daher muss die Jav Datei zusätzlich auch als Java Datei vorliegen, damit man es initial compilerbar ist. Ich habe die notwendigen Dateien in den Anhang geladen. Auf einem unixoiden System sollte mit dem folgenden Befehl der Test automatisiert werden können. Also zip entpacken, in den Ordner gehen und Befehl ausführen. `rm -f *.class && javac Main.java && java -jar JavaTXCompiler.jar Foo.jav && java Main` Achtung, es sollten keine anderen Class Dateien im aktuellen Ordner liegen, sonst werden diese gelöscht! Die Ausgabe des Befehls variiert wenn man ihn öfter ausführt. Die korrekte Ausgabe wäre "Foo", es wird aber teilweise auch "Object" ausgegeben. Also irgendetwas stimmt wohl in der Typinferenz nicht. ``` TxGenerics Foo: [] JavaGenerics Foo: [] TxGenerics Foo: [] generating Foo.class file ... Foo.class Foo.class file generated Foo ``` ``` TxGenerics Foo: [] JavaGenerics Foo: [] TxGenerics Foo: [] generating Foo.class file ... Foo.class Foo.class file generated Object ```
pl was assigned by i21023 2024-05-16 14:38:05 +00:00
Owner

Ich welchen commit gibt es diesen Bug? Bei mir ist die Datei nicht vorhanden

Ich welchen commit gibt es diesen Bug? Bei mir ist die Datei nicht vorhanden
Author
Collaborator

Der Bug ist im aktuellen Commit 974582f7e5 noch vorhanden. Die Dateien sind im Anhang vom Issue als Archiv 2.zip.

Der Bug ist im aktuellen Commit 974582f7e5 noch vorhanden. Die Dateien sind im Anhang vom Issue als `Archiv 2.zip`.
Author
Collaborator

Eigentlich geht es auch nur um die Foo.jav Datei, du musst also nur diese Datei mit dem Java-TX-Compiler aufrufen, dann müsste er die visit Methode machmal mit dem Typ Foo und manchmal mit dem Typ Object aufrufen. Die anderen Dateien sollten schon compiliert im Archiv liegen.

Eigentlich geht es auch nur um die `Foo.jav` Datei, du musst also nur diese Datei mit dem Java-TX-Compiler aufrufen, dann müsste er die visit Methode machmal mit dem Typ Foo und manchmal mit dem Typ Object aufrufen. Die anderen Dateien sollten schon compiliert im Archiv liegen.
dholle was assigned by pl 2024-05-28 14:35:05 +00:00
Owner

In der Tat muss das Problem im Bytecodegenerierer liegen. Das Resultset hat zwei Lösungen

class Foo {

Foo()({
})::TPH X
TPH N accept(Bar b)({
((b)::Bar.visit Signature: [TPH P, TPH Q]((this)::TPH O))::TPH R;
return;
})::TPH T

Foo()({
super(()) Signature: [TPH V];
})::TPH W

}

RESULT Final: [
[(TPH R = void), (TPH P = java.lang.Object), (TPH N = void), (TPH O = Foo), (TPH Q = void)],
[(TPH Q = void), (TPH N = void), (TPH P = Foo), (TPH R = void), (TPH O = Foo)]]

In der Tat muss das Problem im Bytecodegenerierer liegen. Das Resultset hat zwei Lösungen class Foo { Foo()({ })::TPH X TPH N accept(Bar b)({ ((b)::Bar.visit Signature: [TPH P, TPH Q]((this)::TPH O))::TPH R; return; })::TPH T Foo()({ super(()) Signature: [TPH V]; })::TPH W } RESULT Final: [ [(TPH R = void), (TPH P = java.lang.Object), (TPH N = void), (TPH O = Foo), (TPH Q = void)], [(TPH Q = void), (TPH N = void), (TPH P = Foo), (TPH R = void), (TPH O = Foo)]]
Owner

Ich kann die Methode nicht überladen weil die dann zweimal die selbe Signatur hat. Sieht so aus als würde ich hier die erste Lösung nehmen und die andere wegschmeißen.

Wieso sollte TPH P hier jemals Object sein? this hat doch immer den Typ Foo. Ist die Lösung vielleicht zu generell? Es ist ja beides richtig, nur ist Foo halt der konkretere Typ.

Ich kann die Methode nicht überladen weil die dann zweimal die selbe Signatur hat. Sieht so aus als würde ich hier die erste Lösung nehmen und die andere wegschmeißen. Wieso sollte `TPH P` hier jemals `Object` sein? `this` hat doch immer den Typ `Foo`. Ist die Lösung vielleicht zu generell? Es ist ja beides richtig, nur ist `Foo` halt der konkretere Typ.
Owner

Das liegt daran, dass in Bar.java:

public class Bar{

void visit(Object o){
    System.out.println("Object");
}

void visit(Foo f){
    System.out.println("Foo");
}

}
visit eine überladene Methode ist und damit P = Object eine Altenative ist.

Das liegt daran, dass in Bar.java: public class Bar{ void visit(Object o){ System.out.println("Object"); } void visit(Foo f){ System.out.println("Foo"); } } visit eine überladene Methode ist und damit P = Object eine Altenative ist.
Owner

Habe gerade nochmals mit Julian gesprochen. Es müsste hier in der Tat immer die speziellste Methode ausgesucht werden. Bei der Unifikation wird das schwierig, weil bei ungetypten Überladungen die Typen ja noch nicht bekannt sind. Kann man die speziellste Typisierung bei der Bytecodegenerierung noch feststellen?

Habe gerade nochmals mit Julian gesprochen. Es müsste hier in der Tat immer die speziellste Methode ausgesucht werden. Bei der Unifikation wird das schwierig, weil bei ungetypten Überladungen die Typen ja noch nicht bekannt sind. Kann man die speziellste Typisierung bei der Bytecodegenerierung noch feststellen?
Owner

Ich kann ohne weiteres feststellen ob eine Methode mit einer anderen kollidieren würde. Ich denke mal man müsste die TPHs der beiden Methoden vergleichen und da irgendwie feststellen welche konkreter ist. Was die Details angeht bin ich mir aber nicht sicher, gibt es eine gute Metrik um festzustellen welche Methode konkreter ist?

Ich kann ohne weiteres feststellen ob eine Methode mit einer anderen kollidieren würde. Ich denke mal man müsste die TPHs der beiden Methoden vergleichen und da irgendwie feststellen welche konkreter ist. Was die Details angeht bin ich mir aber nicht sicher, gibt es eine gute Metrik um festzustellen welche Methode konkreter ist?
Owner

Man muss während der Umwandlung vom AST -> TargetAST die TPHs der jeweiligen Methdenaufrufe finden.
Der Methodenaufruf wird nur für den speziellsten Fall generiert
Es werden Überladungen nur den Fällen konstruiert, in denen es keinen speziellsten Fall gibt.

Man muss während der Umwandlung vom AST -> TargetAST die TPHs der jeweiligen Methdenaufrufe finden. Der Methodenaufruf wird nur für den speziellsten Fall generiert Es werden Überladungen nur den Fällen konstruiert, in denen es keinen speziellsten Fall gibt.
dholle referenced this issue from a commit 2024-06-13 15:23:23 +00:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
3 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: JavaTX/JavaCompilerCore#332
No description provided.