typetools / typetools/checker-framework

@LessThan treatment of & bitwise mask operation

Open
#2,399 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

False Positive (false warning or imprecision) good first issue Index
Dominant language
Java
Stars
1.1k
Forks
440
Avg merge
1d 12h
Merged PRs (30d)
134

Description

Consider this snippet:

import org.checkerframework.checker.index.qual.LessThan;
import org.checkerframework.common.value.qual.IntRange;

public class Testing {

    private static @IntRange(from = 0, to = 63) int firstNumber;

    private static void method() {
        @LessThan("this.firstNumber") int secondNumber = firstNumber & 7; // Error here
        firstNumber -= secondNumber; // Error here
    }
}

Running javac -processor org.checkerframework.checker.index.IndexChecker Testing.java issues two errors:

Error:(10, 83) java: [assignment.type.incompatible] incompatible types in assignment.
  found   : @LessThanUnknown int
  required: @LessThan("Testing.firstNumber") int
Error:(11, 21) java: [compound.assignment.type.incompatible] incompatible result type in compound assignment.
  found   : @UnknownVal int
  required: @IntRange(from=0, to=63) int

The first error tells that the checker doesn't know that 'firstNumber & 7' is less than 'firstNumber' (or equal). Note that for non-negative numbers, (number & 7) is the same as (number % 8). Changing @IntRange(from = 0, to = 63) ---> @IntRange(from = 1, to = 63), the first error disappears. Now consider the following snippet:

import org.checkerframework.checker.index.qual.IndexFor;
import org.checkerframework.checker.index.qual.LessThan;
import org.checkerframework.common.value.qual.ArrayLen;

public class Testing {

    private static int @ArrayLen(64) [] array;

    private static @IndexFor("this.array") int firstNumber;

    private static void method() {
        @LessThan("this.firstNumber") int secondNumber = firstNumber & 7; // Error here
        firstNumber -= secondNumber;
    }
}

The only difference is that firstNumber is annotated with @IndexFor, pointing to an array with 64 elements. It should take the same values as before (@IntRange(from = 0, to = 63)). However, the second error disappears. Maybe that's because the checker can't make the connection between @IntRange() and @IndexFor() correctly.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the two examples in Testing.java using javac with org.checkerframework.checker.index.IndexChecker. Start by tracing how the checker handles the bitwise & operation and the relationship between @IntRange and @IndexFor. Done means the valid assignments and compound assignment are accepted without losing the relevant range or index information.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.