Kovarianz funktioniert nicht wie gewollt. #347

Closed
opened 2024-09-18 12:11:58 +00:00 by RubenKraft · 2 comments
Collaborator

Im momentanen Testcase beim SwitchAppend wird das Element immer Object.

sealed interface List<T> permits LinkedElem, Elem {}

public record LinkedElem<T>(T a, List<T> l) implements List<T> {}
public record Elem<T>(T a) implements List<T> {}

public class SwitchAppend {
   public append(l1, l2) {
       return switch(l1) {
            //a ist immer vom Typ Object und nicht String bspw.
           case LinkedElem(a, Elem(e)) -> new LinkedElem<>(a, new LinkedElem<>(e, l2)); 
           case LinkedElem(a, r) -> new LinkedElem<>(a, append(r, l2));
           //Alternativ:
	       //case LinkedElem(a, LinkedElem(e, r)) -> new LinkedElem<>(a, append(new LinkedElem(e, r), l2));
       };
   }
}

Dieses Problem sollte durch die Kovarianz des Switch-Statements behoben werden.

Mittels diesem Code-Snippet wird die Kovarianz für das Switch-Statement gesetzt:

//Varianz wird verändernt, später dann Constraints für jeden Case erstellt. Also bspw. case1 <. switch
if(switchStmt.getSwitch().getType() instanceof TypePlaceholder){
           ((TypePlaceholder) switchStmt.getSwitch().getType()).setVariance(1);
       }

Hier nochmal der Code in dem die Constraints erstellt werden.

  if (caseExpressionType == null) {
            for (var child : switchStmt.getBlocks()) {
                for (var label : child.getLabels()) {
                    if (label.getPattern() == null) {
                        System.out.println("DefaultCase");
                    } else {
                        constraintsSet.addUndConstraint(
                                new Pair(
                                        label.getPattern().getType(),
                                        switchStmt.getSwitch().getType(),
                                        PairOperator.SMALLERDOT,
                                        loc(label.getOffset())
                                )
                        );
                    }
                }
            }
        } else {
            constraintsSet.addUndConstraint(new Pair(caseExpressionType, switchStmt.getSwitch().getType(), PairOperator.EQUALSDOT, loc(switchStmt.getSwitch().getOffset())));
        }

Das Problem, das die Elemente der Liste immernoch vom Typ Object sind, wird dadurch jedoch nicht behoben.

Info

  • Es geht um den SwitchAppend-Test
  • Zum Testen musst solltest du am besten den Default-Case beim SwitchAppend rausnehmen.
Im momentanen Testcase beim SwitchAppend wird das Element immer Object. ```java sealed interface List<T> permits LinkedElem, Elem {} public record LinkedElem<T>(T a, List<T> l) implements List<T> {} public record Elem<T>(T a) implements List<T> {} public class SwitchAppend { public append(l1, l2) { return switch(l1) { //a ist immer vom Typ Object und nicht String bspw. case LinkedElem(a, Elem(e)) -> new LinkedElem<>(a, new LinkedElem<>(e, l2)); case LinkedElem(a, r) -> new LinkedElem<>(a, append(r, l2)); //Alternativ: //case LinkedElem(a, LinkedElem(e, r)) -> new LinkedElem<>(a, append(new LinkedElem(e, r), l2)); }; } } ``` Dieses Problem sollte durch die Kovarianz des Switch-Statements behoben werden. Mittels diesem Code-Snippet wird die Kovarianz für das Switch-Statement gesetzt: ```java //Varianz wird verändernt, später dann Constraints für jeden Case erstellt. Also bspw. case1 <. switch if(switchStmt.getSwitch().getType() instanceof TypePlaceholder){ ((TypePlaceholder) switchStmt.getSwitch().getType()).setVariance(1); } ``` Hier nochmal der Code in dem die Constraints erstellt werden. ```java if (caseExpressionType == null) { for (var child : switchStmt.getBlocks()) { for (var label : child.getLabels()) { if (label.getPattern() == null) { System.out.println("DefaultCase"); } else { constraintsSet.addUndConstraint( new Pair( label.getPattern().getType(), switchStmt.getSwitch().getType(), PairOperator.SMALLERDOT, loc(label.getOffset()) ) ); } } } } else { constraintsSet.addUndConstraint(new Pair(caseExpressionType, switchStmt.getSwitch().getType(), PairOperator.EQUALSDOT, loc(switchStmt.getSwitch().getOffset()))); } ``` Das Problem, das die Elemente der Liste immernoch vom Typ Object sind, wird dadurch jedoch nicht behoben. ## Info - Es geht um den SwitchAppend-Test - Zum Testen musst solltest du am besten den Default-Case beim SwitchAppend rausnehmen.
pl was assigned by RubenKraft 2024-09-18 12:12:19 +00:00
Owner

Ich habe das Ganze jetzt mit dem neusten Commit ausgeführt und es gibt jetzt tatsächlich den gemeinsamen Typ an.
Nur leider passiert das auch wenn ein default case dabei ist. Sollte hier nicht immer Object raus kommen? @RubenKraft Ich glaube du musst noch einen Constraint bei default einfügen.

Ich habe das Ganze jetzt mit dem neusten Commit ausgeführt und es gibt jetzt tatsächlich den gemeinsamen Typ an. Nur leider passiert das auch wenn ein default case dabei ist. Sollte hier nicht immer Object raus kommen? @RubenKraft Ich glaube du musst noch einen Constraint bei default einfügen.
Author
Collaborator

Alles klar, danke dir! Dann hab ich irgendwas verpeilt.

@dholle: Sobald der Default-Case dabei ist wird der Typ zu Object, oder?
Andernfalls wird das ein bisschen kompliziert.

Momentan wird im Code der Default-Case folgendermaßen abgefangen:

 if (label.getPattern() == null) {
            System.out.println("DefaultCase");
 }

Ohne Pattern gibts aber entsprechend auch kein Typ.

Ich hab jetzt ein Constraint gepusht, dass das Problem beheben sollte.
Kannst du dir gerne mal hier anschauen: #406f98e55d

Alles klar, danke dir! Dann hab ich irgendwas verpeilt. @dholle: Sobald der Default-Case dabei ist wird der Typ zu Object, oder? Andernfalls wird das ein bisschen kompliziert. Momentan wird im Code der Default-Case folgendermaßen abgefangen: ```java if (label.getPattern() == null) { System.out.println("DefaultCase"); } ``` Ohne Pattern gibts aber entsprechend auch kein Typ. Ich hab jetzt ein Constraint gepusht, dass das Problem beheben sollte. Kannst du dir gerne mal hier anschauen: [#406f98e55d](https://gitea.hb.dhbw-stuttgart.de/JavaTX/JavaCompilerCore/commit/406f98e55dfabcca8610e30fe68a6cbc00f39162)
Sign in to join this conversation.
No Milestone
No project
No Assignees
2 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#347
No description provided.