typetools / typetools/checker-framework

KeyFor annotation lost in stream

Open
#4,668 1 comment 0 reactions 1 assignee View on GitHub

@smillst is already working on this.

Since May 20, 2021.

Dominant language
Java
Stars
1.1k
Forks
440
Avg merge
1d 12h
Merged PRs (30d)
134

Description

In the below code I get a nullness warning when accessing endTimes inside the stream even though cattegoryInfo is marked as having the same keys as endTimes. It looks like the call to entrySet doesn't pass along the KeyFor annotation of the generic type. When I separate the call to entrySet to be a separate variable I cannot annotate the variable with a KeyFor{{"endtimes"}) without checker giving a warning.

This is using checker 3.13.0 and OpenJDK 11.

/home/jpschewe/projects/checker-bugs/src/main/java/net/mtu/eggplant/checker/keyfor_stream/KeyForStream.java:43: error: [argument] incompatible argument for parameter endTime of FinalistDBRow.
                                        endTimes.get(entry.getKey()),
                                                    ^
  found   : @Initialized @Nullable LocalTime
  required: @Initialized @NonNull LocalTime

FinalistDBRow.java

package net.mtu.eggplant.checker.keyfor_stream;

import java.time.LocalTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;


public final class FinalistDBRow {

  public FinalistDBRow(final LocalTime time,
                       final LocalTime endTime,
                       final Map<String, Integer> categories) {
    this.time = time;
    this.endTime = endTime;
    this.categories = Collections.unmodifiableMap(new HashMap<>(categories));
  }

  private final LocalTime time;

  private final LocalTime endTime;

  private final Map<String, Integer> categories;

}

KeyForStream.java

package net.mtu.eggplant.checker.keyfor_stream;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.ResultSet;

import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.stream.Collectors;

import java.time.LocalTime;

import org.checkerframework.checker.nullness.qual.KeyFor;

import static org.checkerframework.checker.nullness.util.NullnessUtil.castNonNull;

public class KeyForStream {

  public void method(final Connection connection) throws SQLException {
    try (
         PreparedStatement getSchedule = connection.prepareStatement("SELECT category, judge_time, judge_end_time, team_number FROM finalist_schedule WHERE tournament = ? AND division = ?")) {
      getSchedule.setInt(1, 5);
      getSchedule.setString(2, "awardGroup");
    
      final Map<LocalTime, LocalTime> endTimes = new HashMap<>();
      final Map<@KeyFor("endTimes") LocalTime, Map<String, Integer>> categoryInfo = new HashMap<>();
      try (ResultSet schedule = getSchedule.executeQuery()) {
        while (schedule.next()) {
          final String categoryName = castNonNull(schedule.getString(1));
          final LocalTime judgeTime = castNonNull(schedule.getTime(2)).toLocalTime();
          final LocalTime judgeEndTime = castNonNull(schedule.getTime(3)).toLocalTime();
          final Integer teamNumber = Integer.valueOf(schedule.getInt(4));

          endTimes.put(judgeTime, judgeEndTime);
          categoryInfo.computeIfAbsent(judgeTime, k -> new HashMap<>()).put(categoryName, teamNumber);
        } // foreach result
      } // allocate ResultSet

      final List<FinalistDBRow> rows = categoryInfo.entrySet().stream() //
        .map(entry -> new FinalistDBRow(entry.getKey(),
                                        endTimes.get(entry.getKey()),
                                        entry.getValue())) //
        .collect(Collectors.toList());
    }
  }

}

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.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.