Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Scala 3 Java interop: method on base class called instead of method on derived class #17073

Unanswered
Discussion options

Not sure if it's a bug or to be expected. We ran into runtime issues after upgrading to Scala 3.

//> using scala 3
//> using repository "https://maven.atlassian.com/repository/public"
//> using lib "com.atlassian.webhooks:atlassian-webhooks-api:6.1.6"
//> using lib "com.atlassian.bitbucket.server:bitbucket-webhooks-api:7.14.0"
import com.atlassian.bitbucket.webhook.WebhookScopeAdapter
import com.atlassian.webhooks._
val createRequest = WebhookCreateRequest.builder
 .name("name")
 .url("url")
 .build()
println("Runs with scala 2")

Basically the class hierarchy of WebhookCreateRequest looks like (simplified):

public class CreateRequest extends AbstractRequest {
 
 private CreateRequest(Builder builder) { super(builder); }
 public static Builder builder() { return new Builder();}
 public static class Builder extends AbstractRequest.AbstractBuilder<Builder> {
 protected Builder self() { return this; }
 public build() { return new CreateRequest(this);}
 }
}
public abstract class AbstractRequest {
 abstract static class AbstractBuilder<B extends AbstractBuilder<B>> {
 private String name;
 private String url;
 AbstractBuilder() {}
 protected abstract B self();
 public B name(String value) {
 this.name = value;
 return this.self();
 }
 public B url(String value) {
 this.url = value;
 return this.self();
 }
 }
}

Now the inner class AbstractBuilder is not public, and when the Scala compiler calls the method on it instead of CreateRequest an IllegalAccessException is called.

The bytecode output of Scala 2/ Java compilation

// 10: invokestatic #30 // Method .../WebhookCreateRequest.builder:()L.../WebhookCreateRequest$Builder;
// 13: ldc #32 // String name
// 15: invokevirtual #35 // Method .../WebhookCreateRequest$Builder.name:(Ljava/lang/String;)L.../AbstractWebhookRequest$AbstractBuilder;
// 18: checkcast #12 // class .../WebhookCreateRequest$Builder
// 21: ldc #37 // String url
// 23: invokevirtual #39 // Method .../WebhookCreateRequest$Builder.url:(Ljava/lang/String;)L.../AbstractWebhookRequest$AbstractBuilder;

Compared to Scala 3 (issue on last line)

// 10: invokestatic #34 // Method .../WebhookCreateRequest.builder:()L.../WebhookCreateRequest$Builder;
// 13: ldc #36 // String name
// 15: invokevirtual #39 // Method .../WebhookCreateRequest$Builder.name:(Ljava/lang/String;)L.../AbstractWebhookRequest$AbstractBuilder;
// 18: ldc #41 // String url
// 20: invokevirtual #43 // Method .../AbstractWebhookRequest$AbstractBuilder.url:(Ljava/lang/String;)L.../AbstractWebhookRequest$AbstractBuilder;

Is there a reason the second and all further chained builder calls (here the url()) call) are compiled to call the base class method?

You must be logged in to vote

Replies: 0 comments

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
1 participant

AltStyle によって変換されたページ (->オリジナル) /