error-prone icon indicating copy to clipboard operation
error-prone copied to clipboard

`@Immutable` does not recognize safe array handling

Open codeleverage opened this issue 1 year ago • 1 comments

The following two examples use defensive cloning on the way in and out.

Example 1

@Immutable
public final class ArbitraryClass {

  private final String[] array;

  public ArbitraryClass(String[] array) {
    this.array = array.clone();
  }

  public String[] array() {
    return this.array.clone();
  }
}

Example 2

@Immutable
public record ArbitraryRecord(String[] array) {

  public ArbitraryRecord(String[] array) {
    this.array = array.clone();
  }

  public String[] array() {
    return this.array.clone();
  }
}

I expected both of these to be considered immutable, but get the following error:

[Immutable] type annotated with @Immutable could not be proven immutable: 'ArbitraryClass' has field 'array' of type 'java.lang.String[]', arrays are mutable

Am I missing a way these examples aren't actually immutable? Or can @Immutable processing be improved to allow for this?

codeleverage avatar Mar 21 '24 11:03 codeleverage

The check tries to enforce the sort of deep immutability described here. It encourages using types like ImmutableList<String> instead of String[], because they don't require reasoning about whether they can be mutated at runtime, the contract of ImmutableList guarantees it's always going to be immutable.

So I agree those examples are immutable, but they're probably not a pattern that the check is going to recognize.

cushon avatar Mar 21 '24 14:03 cushon

Another way to phrase that: the check doesn't do any kind of flow analysis to check whether mutable innards are used in a way which leads to outward immutability.

If I really couldn't use an immutable container, I'd add a suppression with a comment: @SuppressWarnings("Immutable") // cloned on the way in and out.

graememorgan avatar Apr 03 '24 12:04 graememorgan

Ok, thanks for the clarification.

codeleverage avatar Apr 04 '24 22:04 codeleverage