Falscher Target Type für Lambdas #325
Labels
No Label
Codegen
confirmed
duplicate
Eclipse-Plugin
Feature Request
generics
in progress
invalid
JavaCompilerCore
needs info
Parser
Trash
Type
Unify
won't fix
works for me
No Milestone
No project
No Assignees
3 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: JavaTX/JavaCompilerCore#325
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Ich glaube die Typinferenz funktioniert mit Lambda Ausdrücken, die ein bestimmtes funktionales Interface als Target Type benötigen nur lokal.
Beispiel
Dieser Code kompiliert zwar, er inferiert aber den FunN Typ anstatt
java.util.function.Function
für die Lambda Expression.Zur Laufzeit gibt es entsprechend einen Fehler weil
java.util.stream.Stream.map
Function
als Parameter erwartet.Im Bytecode steht also folgendes:
46: invokedynamic #56, 0 // InvokeDynamic #0:apply:(LFoo;)LFun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$;
...statt
50: invokedynamic #60, 0 // InvokeDynamic #0:apply:(LFoo;)Ljava/util/function/Function;
Zweiteres wird korrekt generiert, wenn die Lambda Expression direkt dem der Methode map übergeben wird, also:
Der Typinferenz Algorithmus sollte ja eigentlich in der Lage sein dies zu erkennen.
Auch im Paper von 2017 wurde in Kapitel 7 schon ein Beispiel mit dem gleichen Prinzip wie oben gegeben:
@pl Wir haben heute schon drüber gesprochen aber ich glaube es gibt doch noch einen Fehler.
Der
contextType
, also der aus der Signatur macht nur dann Sinn, wenn das Lambda inline definiert wird.Was hier passiert ist, dass die lokale Variable
func
schon den falschen Typ hat (Fun1$$
) und ich an der Stelle wo der Methodenaufruf stattfindet das Lambda ja bereits generiert habe. Ich könnte es höchstens noch casten aber das funktioniert ja auch nicht.TPH AF
muss also schon aufjava.util.function.Function
zeigen, sonst funktioniert es nicht. Sowieso ist diesercontextType
den ich hier eingeführt habe etwas seltsam, da ja eigentlich die Typinferenz schon die richtigen Typen liefern sollte.Das wird leider nicht klappen. Der Typ von
func
mussFun1$$
sein. Was machts Du wenn das Programm wie folgt erweitert wird:Es wurde eine Lösung implementiert, das Beispiel funktioniert jetzt.
Was passiert ist, dass jeweils wenn ein Lambda in einen anderen Typ überführt wird, wird eine Art Wrapperklasse erzeugt, welche den anderen Typ implementiert. Diese macht nichts anderes als die orginale Funktion auszuführen.