Skip to content
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

[BUG] Using @StandardException and @AllArgConstructor on a class with two non-primitive fields creates ambiguous constructor #3665

Open
fralalonde opened this issue May 7, 2024 · 2 comments
Assignees
Labels
accepted The issue/enhancement is valid, sensible, and explained in sufficient detail bug

Comments

@fralalonde
Copy link

fralalonde commented May 7, 2024

Describe the bug
Using @StandardException and @AllArgConstructor on a class with TWO extra fields creates ambiguous constructor

To Reproduce
Try compiling:

@StandardException
@AllArgsConstructor
public class Failure extends Exception {
    Date today;
    Integer row;
}

fails with the error message:

java: reference to Failure is ambiguous
  both constructor Failure(java.lang.String,java.lang.Throwable) in com.example.demo.Failure and constructor Failure(java.util.Date,java.lang.Integer) in com.example.demo.Failure match

Order of explicit fields does not matter.

Defining only one or more than two fields compiles without issue:

@StandardException
@AllArgsConstructor
public class Failure extends Exception {
    Date today;
}

and

@StandardException
@AllArgsConstructor
public class Failure extends Exception {
    Date today;
    Integer row;
    byte[] data;
}

work as expected, allowing to write code such as

@StandardException
@AllArgsConstructor
@ToString
public class Failure extends Exception {
    @With
    Date today;
    @With
    Integer row;
    @With
    byte[] data;
}

[...]

throw new Failure("ouch", cause)
        .withData(new byte[] {1,2,3})
        .withToday(LocalDateTime.now())
        .withRow(44);

NOTE: ToString generated code does not include the @StandardException fields message and cause.

Changing one or many fields to a primitive type (e.g. Integer -> int) also fixes the issue:

public class Failure extends RuntimeException {
    @With
    LocalDateTime today;
    @With
    int row;
}

Expected behavior

It is expected that a class annotated with both @StandardException and @AllArgsConstructor defining TWO non-primitive fields should successfully compile, similarly to a class defining one, three or more non-primitive parameters.

The following code:

@StandardException
@AllArgsConstructor
@Getter
@ToString
public class Failure extends RuntimeException {
    @With
    LocalDateTime today;
    @With
    Integer row;
}

should be converted to the equivalent (compiling) code:

@AllArgsConstructor
@Getter
@ToString
public class Failure extends RuntimeException {
    @With
    LocalDateTime today;
    @With
    Integer row;

    final String message;
    final Throwable cause;

    public Failure() {
        this(null, null);
    }

    public Failure(String message) {
        this(message, null);
    }

    public Failure(Throwable cause) {
        this(null, cause);
    }

    public Failure(String message, Throwable cause) {
        this.message = message;
        this.cause = cause;
    }
}

Looking at it this way, my hypothesis is that both @ToString and @AllArgs ignore the added fields from @StandardException. I haven't looked at Lombok code in a long time but it seems that @StandardException should have priority into extending the class so that other annotations can pickup its additions and process them like regular code.

Version info (please complete the following information):

  • Lombok version: 1.18.30
  • Platform: javac 21.0.2
@fralalonde
Copy link
Author

possibly related: #3456

@Rawi01
Copy link
Collaborator

Rawi01 commented May 23, 2024

Great bug report, can reproduce your problem. The compilation error occurs because the constructor generated by @StandardException invokes this(null, null) which is ambiguous.

Simply changing the handler order doesn't work because @StandardException doesn't add the message and cause fields, it uses the parent fields.

Yes, the @Builder support is related, both handlers use the same code to collect fields.

@Rawi01 Rawi01 added bug accepted The issue/enhancement is valid, sensible, and explained in sufficient detail labels May 23, 2024
@Rawi01 Rawi01 self-assigned this May 23, 2024
Rawi01 added a commit to Rawi01/lombok that referenced this issue May 23, 2024
Rawi01 added a commit to Rawi01/lombok that referenced this issue May 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted The issue/enhancement is valid, sensible, and explained in sufficient detail bug
Projects
None yet
Development

No branches or pull requests

2 participants