From 28d5cc46646904c2f4911a1c6e70edc3f6be3330 Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Tue, 10 Dec 2024 18:38:04 -0500 Subject: [PATCH 01/82] Remove GitHub CI --- .github/workflows/submit.yml | 1626 ---------------------------------- 1 file changed, 1626 deletions(-) delete mode 100644 .github/workflows/submit.yml diff --git a/.github/workflows/submit.yml b/.github/workflows/submit.yml deleted file mode 100644 index 25e90e9d45d..00000000000 --- a/.github/workflows/submit.yml +++ /dev/null @@ -1,1626 +0,0 @@ -name: Pre-submit tests - -on: - push: - branches-ignore: - - master - - pr/* - workflow_dispatch: - inputs: - platforms: - description: "Platform(s) to execute on" - required: true - default: "Linux additional (hotspot only), Linux x64, Linux x86, Windows x64, macOS x64" - -jobs: - prerequisites: - name: Prerequisites - runs-on: "ubuntu-20.04" - outputs: - should_run: ${{ steps.check_submit.outputs.should_run }} - bundle_id: ${{ steps.check_bundle_id.outputs.bundle_id }} - platform_linux_additional: ${{ steps.check_platforms.outputs.platform_linux_additional }} - platform_linux_x64: ${{ steps.check_platforms.outputs.platform_linux_x64 }} - platform_linux_x86: ${{ steps.check_platforms.outputs.platform_linux_x86 }} - platform_windows_x64: ${{ steps.check_platforms.outputs.platform_windows_x64 }} - platform_macos_x64: ${{ steps.check_platforms.outputs.platform_macos_x64 }} - platform_macos_aarch64: ${{ steps.check_platforms.outputs.platform_macos_aarch64 }} - dependencies: ${{ steps.check_deps.outputs.dependencies }} - - steps: - - name: Check if submit tests should actually run depending on secrets and manual triggering - id: check_submit - run: echo "::set-output name=should_run::${{ github.event.inputs.platforms != '' || (!secrets.JDK_SUBMIT_FILTER || startsWith(github.ref, 'refs/heads/submit/')) }}" - - - name: Check which platforms should be included - id: check_platforms - run: | - echo "::set-output name=platform_linux_additional::${{ contains(github.event.inputs.platforms, 'linux additional (hotspot only)') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'linux additional (hotspot only)'))) }}" - echo "::set-output name=platform_linux_x64::${{ contains(github.event.inputs.platforms, 'linux x64') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'linux x64'))) }}" - echo "::set-output name=platform_linux_x86::${{ contains(github.event.inputs.platforms, 'linux x86') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'linux x86'))) }}" - echo "::set-output name=platform_windows_x64::${{ contains(github.event.inputs.platforms, 'windows x64') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'windows x64'))) }}" - echo "::set-output name=platform_macos_x64::${{ contains(github.event.inputs.platforms, 'macos x64') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'macos x64'))) }}" - echo "::set-output name=platform_macos_aarch64::${{ contains(github.event.inputs.platforms, 'macos aarch64') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'macos aarch64'))) }}" - if: steps.check_submit.outputs.should_run != 'false' - - - name: Determine unique bundle identifier - id: check_bundle_id - run: echo "::set-output name=bundle_id::${GITHUB_ACTOR}_${GITHUB_SHA:0:8}" - if: steps.check_submit.outputs.should_run != 'false' - - - name: Checkout the source - uses: actions/checkout@v2 - with: - path: jdk - if: steps.check_submit.outputs.should_run != 'false' - - - name: Determine versions and locations to be used for dependencies - id: check_deps - run: "echo ::set-output name=dependencies::`cat make/conf/version-numbers.conf make/conf/test-dependencies | sed -e '1i {' -e 's/#.*//g' -e 's/\"//g' -e 's/\\(.*\\)=\\(.*\\)/\"\\1\": \"\\2\",/g' -e '$s/,\\s\\{0,\\}$/\\}/'`" - working-directory: jdk - if: steps.check_submit.outputs.should_run != 'false' - - - name: Print extracted dependencies to the log - run: "echo '${{ steps.check_deps.outputs.dependencies }}'" - if: steps.check_submit.outputs.should_run != 'false' - - - name: Determine the jtreg ref to checkout - run: "echo JTREG_REF=jtreg-${{ fromJson(steps.check_deps.outputs.dependencies).JTREG_VERSION }}+${{ fromJson(steps.check_deps.outputs.dependencies).JTREG_BUILD }} >> $GITHUB_ENV" - if: steps.check_submit.outputs.should_run != 'false' - - - name: Check if a jtreg image is present in the cache - id: jtreg - uses: actions/cache@v2 - with: - path: ~/jtreg/ - key: jtreg-${{ env.JTREG_REF }}-v1 - if: steps.check_submit.outputs.should_run != 'false' - - - name: Checkout the jtreg source - uses: actions/checkout@v2 - with: - repository: "openjdk/jtreg" - ref: ${{ env.JTREG_REF }} - path: jtreg - if: steps.check_submit.outputs.should_run != 'false' && steps.jtreg.outputs.cache-hit != 'true' - - - name: Build jtreg - run: bash make/build.sh --jdk ${JAVA_HOME_8_X64} - working-directory: jtreg - if: steps.check_submit.outputs.should_run != 'false' && steps.jtreg.outputs.cache-hit != 'true' - - - name: Move jtreg image to destination folder - run: mv build/images/jtreg ~/ - working-directory: jtreg - if: steps.check_submit.outputs.should_run != 'false' && steps.jtreg.outputs.cache-hit != 'true' - - - name: Store jtreg for use by later steps - uses: actions/upload-artifact@v2 - with: - name: transient_jtreg_${{ steps.check_bundle_id.outputs.bundle_id }} - path: ~/jtreg/ - if: steps.check_submit.outputs.should_run != 'false' - - linux_x64_build: - name: Linux x64 - runs-on: "ubuntu-20.04" - needs: prerequisites - if: needs.prerequisites.outputs.should_run != 'false' && (needs.prerequisites.outputs.platform_linux_x64 != 'false' || needs.prerequisites.outputs.platform_linux_additional == 'true') - - strategy: - fail-fast: false - matrix: - flavor: - - build release - - build debug - include: - - flavor: build debug - flags: --enable-debug - artifact: -debug - - env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" - BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" - BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_FILENAME }}" - BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_URL }}" - BOOT_JDK_SHA256: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_SHA256 }}" - - steps: - - name: Checkout the source - uses: actions/checkout@v2 - with: - path: jdk - - - name: Restore boot JDK from cache - id: bootjdk - uses: actions/cache@v2 - with: - path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} - key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 - - - name: Download boot JDK - run: | - mkdir -p "${HOME}/bootjdk/${BOOT_JDK_VERSION}" - wget -O "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" "${BOOT_JDK_URL}" - echo "${BOOT_JDK_SHA256} ${HOME}/bootjdk/${BOOT_JDK_FILENAME}" | sha256sum -c >/dev/null - - tar -xf "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" -C "${HOME}/bootjdk/${BOOT_JDK_VERSION}" - mv "${HOME}/bootjdk/${BOOT_JDK_VERSION}/"*/* "${HOME}/bootjdk/${BOOT_JDK_VERSION}/" - if: steps.bootjdk.outputs.cache-hit != 'true' - - - name: Restore jtreg artifact - id: jtreg_restore - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - continue-on-error: true - - - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - if: steps.jtreg_restore.outcome == 'failure' - - - name: Checkout gtest sources - uses: actions/checkout@v2 - with: - repository: "google/googletest" - ref: "release-${{ fromJson(needs.prerequisites.outputs.dependencies).GTEST_VERSION }}" - path: gtest - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install gcc-10=10.3.0-1ubuntu1~20.04 g++-10=10.3.0-1ubuntu1~20.04 libxrandr-dev libxtst-dev libcups2-dev libasound2-dev - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 - - - name: Configure - run: > - bash configure - --with-conf-name=linux-x64 - ${{ matrix.flags }} - --with-version-opt=${GITHUB_ACTOR}-${GITHUB_SHA} - --with-version-build=0 - --with-boot-jdk=${HOME}/bootjdk/${BOOT_JDK_VERSION} - --with-jtreg=${HOME}/jtreg - --with-gtest=${GITHUB_WORKSPACE}/gtest - --with-default-make-target="product-bundles test-bundles" - --with-zlib=system - --enable-jtreg-failure-handler - working-directory: jdk - - - name: Build - run: make CONF_NAME=linux-x64 - working-directory: jdk - - - name: Persist test bundles - uses: actions/upload-artifact@v2 - with: - name: transient_jdk-linux-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} - path: | - jdk/build/linux-x64/bundles/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x64_bin${{ matrix.artifact }}.tar.gz - jdk/build/linux-x64/bundles/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x64_bin-tests${{ matrix.artifact }}.tar.gz - - linux_x64_test: - name: Linux x64 - runs-on: "ubuntu-20.04" - needs: - - prerequisites - - linux_x64_build - - strategy: - fail-fast: false - matrix: - test: - - jdk/tier1 part 1 - - jdk/tier1 part 2 - - jdk/tier1 part 3 - - langtools/tier1 - - hs/tier1 common - - hs/tier1 compiler - - hs/tier1 gc - - hs/tier1 runtime - - hs/tier1 serviceability - include: - - test: jdk/tier1 part 1 - suites: test/jdk/:tier1_part1 - - test: jdk/tier1 part 2 - suites: test/jdk/:tier1_part2 - - test: jdk/tier1 part 3 - suites: test/jdk/:tier1_part3 - - test: langtools/tier1 - suites: test/langtools/:tier1 - - test: hs/tier1 common - suites: test/hotspot/jtreg/:tier1_common - artifact: -debug - - test: hs/tier1 compiler - suites: test/hotspot/jtreg/:tier1_compiler - artifact: -debug - - test: hs/tier1 gc - suites: test/hotspot/jtreg/:tier1_gc - artifact: -debug - - test: hs/tier1 runtime - suites: test/hotspot/jtreg/:tier1_runtime - artifact: -debug - - test: hs/tier1 serviceability - suites: test/hotspot/jtreg/:tier1_serviceability - artifact: -debug - - env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" - BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" - BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_FILENAME }}" - BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_URL }}" - BOOT_JDK_SHA256: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_SHA256 }}" - - steps: - - name: Checkout the source - uses: actions/checkout@v2 - - - name: Restore boot JDK from cache - id: bootjdk - uses: actions/cache@v2 - with: - path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} - key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 - - - name: Download boot JDK - run: | - mkdir -p "${HOME}/bootjdk/${BOOT_JDK_VERSION}" - wget -O "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" "${BOOT_JDK_URL}" - echo "${BOOT_JDK_SHA256} ${HOME}/bootjdk/${BOOT_JDK_FILENAME}" | sha256sum -c >/dev/null - - tar -xf "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" -C "${HOME}/bootjdk/${BOOT_JDK_VERSION}" - mv "${HOME}/bootjdk/${BOOT_JDK_VERSION}/"*/* "${HOME}/bootjdk/${BOOT_JDK_VERSION}/" - if: steps.bootjdk.outputs.cache-hit != 'true' - - - name: Restore jtreg artifact - id: jtreg_restore - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - continue-on-error: true - - - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - if: steps.jtreg_restore.outcome == 'failure' - - - name: Restore build artifacts - id: build_restore - uses: actions/download-artifact@v2 - with: - name: transient_jdk-linux-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jdk-linux-x64${{ matrix.artifact }} - continue-on-error: true - - - name: Restore build artifacts (retry) - uses: actions/download-artifact@v2 - with: - name: transient_jdk-linux-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jdk-linux-x64${{ matrix.artifact }} - if: steps.build_restore.outcome == 'failure' - - - name: Unpack jdk - run: | - mkdir -p "${HOME}/jdk-linux-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x64_bin${{ matrix.artifact }}" - tar -xf "${HOME}/jdk-linux-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x64_bin${{ matrix.artifact }}.tar.gz" -C "${HOME}/jdk-linux-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x64_bin${{ matrix.artifact }}" - - - name: Unpack tests - run: | - mkdir -p "${HOME}/jdk-linux-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x64_bin-tests${{ matrix.artifact }}" - tar -xf "${HOME}/jdk-linux-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x64_bin-tests${{ matrix.artifact }}.tar.gz" -C "${HOME}/jdk-linux-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x64_bin-tests${{ matrix.artifact }}" - - - name: Find root of jdk image dir - run: | - imageroot=`find ${HOME}/jdk-linux-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x64_bin${{ matrix.artifact }} -name release -type f` - echo "imageroot=`dirname ${imageroot}`" >> $GITHUB_ENV - - - name: Run tests - run: > - JDK_IMAGE_DIR=${{ env.imageroot }} - TEST_IMAGE_DIR=${HOME}/jdk-linux-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x64_bin-tests${{ matrix.artifact }} - BOOT_JDK=${HOME}/bootjdk/${BOOT_JDK_VERSION} - JT_HOME=${HOME}/jtreg - make test-prebuilt - CONF_NAME=run-test-prebuilt - LOG_CMDLINES=true - JTREG_VERBOSE=fail,error,time - TEST="${{ matrix.suites }}" - TEST_OPTS_JAVA_OPTIONS= - JTREG_KEYWORDS="!headful" - JTREG="JAVA_OPTIONS=-XX:-CreateCoredumpOnCrash" - - - name: Check that all tests executed successfully - if: always() - run: > - if ! grep --include=test-summary.txt -lqr build/*/test-results -e "TEST SUCCESS" ; then - cat build/*/test-results/*/text/newfailures.txt ; - exit 1 ; - fi - - - name: Create suitable test log artifact name - if: always() - run: echo "logsuffix=`echo ${{ matrix.test }} | sed -e 's!/!_!'g -e 's! !_!'g`" >> $GITHUB_ENV - - - name: Package test results - if: always() - working-directory: build/run-test-prebuilt/test-results/ - run: > - zip -r9 - "$HOME/linux-x64${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip" - . - continue-on-error: true - - - name: Package test support - if: always() - working-directory: build/run-test-prebuilt/test-support/ - run: > - zip -r9 - "$HOME/linux-x64${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip" - . - -i *.jtr - -i */hs_err*.log - -i */replay*.log - continue-on-error: true - - - name: Persist test results - if: always() - uses: actions/upload-artifact@v2 - with: - path: ~/linux-x64${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip - continue-on-error: true - - - name: Persist test outputs - if: always() - uses: actions/upload-artifact@v2 - with: - path: ~/linux-x64${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip - continue-on-error: true - - linux_additional_build: - name: Linux additional - runs-on: "ubuntu-20.04" - needs: - - prerequisites - - linux_x64_build - if: needs.prerequisites.outputs.should_run != 'false' && needs.prerequisites.outputs.platform_linux_additional != 'false' - - strategy: - fail-fast: false - matrix: - flavor: - - hs x64 build only - - hs x64 zero build only - - hs x64 minimal build only - - hs x64 optimized build only - - hs aarch64 build only - - hs arm build only - - hs s390x build only - - hs ppc64le build only - include: - - flavor: hs x64 build only - flags: --enable-debug --disable-precompiled-headers - - flavor: hs x64 zero build only - flags: --enable-debug --disable-precompiled-headers --with-jvm-variants=zero - - flavor: hs x64 minimal build only - flags: --enable-debug --disable-precompiled-headers --with-jvm-variants=minimal - - flavor: hs x64 optimized build only - flags: --with-debug-level=optimized --disable-precompiled-headers - - flavor: hs aarch64 build only - flags: --enable-debug --disable-precompiled-headers - debian-arch: arm64 - gnu-arch: aarch64 - - flavor: hs arm build only - flags: --enable-debug --disable-precompiled-headers - debian-arch: armhf - gnu-arch: arm - gnu-flavor: eabihf - - flavor: hs s390x build only - flags: --enable-debug --disable-precompiled-headers - debian-arch: s390x - gnu-arch: s390x - - flavor: hs ppc64le build only - flags: --enable-debug --disable-precompiled-headers - debian-arch: ppc64el - gnu-arch: powerpc64le - - env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" - BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" - BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_FILENAME }}" - BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_URL }}" - BOOT_JDK_SHA256: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_SHA256 }}" - - steps: - - name: Checkout the source - uses: actions/checkout@v2 - with: - path: jdk - - - name: Restore boot JDK from cache - id: bootjdk - uses: actions/cache@v2 - with: - path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} - key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 - - - name: Download boot JDK - run: | - mkdir -p "${HOME}/bootjdk/${BOOT_JDK_VERSION}" - wget -O "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" "${BOOT_JDK_URL}" - echo "${BOOT_JDK_SHA256} ${HOME}/bootjdk/${BOOT_JDK_FILENAME}" | sha256sum -c >/dev/null - - tar -xf "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" -C "${HOME}/bootjdk/${BOOT_JDK_VERSION}" - mv "${HOME}/bootjdk/${BOOT_JDK_VERSION}/"*/* "${HOME}/bootjdk/${BOOT_JDK_VERSION}/" - if: steps.bootjdk.outputs.cache-hit != 'true' - - - name: Restore build JDK - id: build_restore - uses: actions/download-artifact@v2 - with: - name: transient_jdk-linux-x64_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jdk-linux-x64 - continue-on-error: true - - - name: Restore build JDK (retry) - uses: actions/download-artifact@v2 - with: - name: transient_jdk-linux-x64_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jdk-linux-x64 - if: steps.build_restore.outcome == 'failure' - - - name: Unpack build JDK - run: | - mkdir -p "${HOME}/jdk-linux-x64/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x64_bin" - tar -xf "${HOME}/jdk-linux-x64/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x64_bin.tar.gz" -C "${HOME}/jdk-linux-x64/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x64_bin" - - - name: Find root of build JDK image dir - run: | - build_jdk_root=`find ${HOME}/jdk-linux-x64/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x64_bin -name release -type f` - echo "build_jdk_root=`dirname ${build_jdk_root}`" >> $GITHUB_ENV - - - name: Update apt - run: sudo apt-get update - - - name: Install native host dependencies - run: | - sudo apt-get install gcc-10=10.3.0-1ubuntu1~20.04 g++-10=10.3.0-1ubuntu1~20.04 libxrandr-dev libxtst-dev libcups2-dev libasound2-dev - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 - if: matrix.debian-arch == '' - - - name: Install cross-compilation host dependencies - run: sudo apt-get install gcc-10-${{ matrix.gnu-arch }}-linux-gnu${{ matrix.gnu-flavor}}=10.3.0-1ubuntu1~20.04cross1 g++-10-${{ matrix.gnu-arch }}-linux-gnu${{ matrix.gnu-flavor}}=10.3.0-1ubuntu1~20.04cross1 - if: matrix.debian-arch != '' - - - name: Cache sysroot - id: cache-sysroot - uses: actions/cache@v2 - with: - path: ~/sysroot-${{ matrix.debian-arch }}/ - key: sysroot-${{ matrix.debian-arch }}-${{ hashFiles('jdk/.github/workflows/submit.yml') }} - if: matrix.debian-arch != '' - - - name: Install sysroot host dependencies - run: sudo apt-get install debootstrap qemu-user-static - if: matrix.debian-arch != '' && steps.cache-sysroot.outputs.cache-hit != 'true' - - - name: Create sysroot - run: > - sudo qemu-debootstrap - --arch=${{ matrix.debian-arch }} - --verbose - --include=fakeroot,symlinks,build-essential,libx11-dev,libxext-dev,libxrender-dev,libxrandr-dev,libxtst-dev,libxt-dev,libcups2-dev,libfontconfig1-dev,libasound2-dev,libfreetype6-dev,libpng-dev - --resolve-deps - buster - ~/sysroot-${{ matrix.debian-arch }} - http://httpredir.debian.org/debian/ - if: matrix.debian-arch != '' && steps.cache-sysroot.outputs.cache-hit != 'true' - - - name: Prepare sysroot for caching - run: | - sudo chroot ~/sysroot-${{ matrix.debian-arch }} symlinks -cr . - sudo chown ${USER} -R ~/sysroot-${{ matrix.debian-arch }} - rm -rf ~/sysroot-${{ matrix.debian-arch }}/{dev,proc,run,sys} - if: matrix.debian-arch != '' && steps.cache-sysroot.outputs.cache-hit != 'true' - - - name: Configure cross compiler - run: | - echo "CC=${{ matrix.gnu-arch }}-linux-gnu${{ matrix.gnu-flavor}}-gcc-10" >> $GITHUB_ENV - echo "CXX=${{ matrix.gnu-arch }}-linux-gnu${{ matrix.gnu-flavor}}-g++-10" >> $GITHUB_ENV - if: matrix.debian-arch != '' - - - name: Configure cross specific flags - run: > - echo "cross_flags= - --openjdk-target=${{ matrix.gnu-arch }}-linux-gnu${{ matrix.gnu-flavor}} - --with-sysroot=${HOME}/sysroot-${{ matrix.debian-arch }}/ - " >> $GITHUB_ENV - if: matrix.debian-arch != '' - - - name: Configure - run: > - bash configure - --with-conf-name=linux-${{ matrix.gnu-arch }}-hotspot - ${{ matrix.flags }} - ${{ env.cross_flags }} - --with-version-opt=${GITHUB_ACTOR}-${GITHUB_SHA} - --with-version-build=0 - --with-boot-jdk=${HOME}/bootjdk/${BOOT_JDK_VERSION} - --with-build-jdk=${{ env.build_jdk_root }} - --with-default-make-target="hotspot" - --with-zlib=system - working-directory: jdk - - - name: Build - run: make CONF_NAME=linux-${{ matrix.gnu-arch }}-hotspot - working-directory: jdk - - linux_x86_build: - name: Linux x86 - runs-on: "ubuntu-20.04" - needs: prerequisites - if: needs.prerequisites.outputs.should_run != 'false' && needs.prerequisites.outputs.platform_linux_x86 != 'false' - - strategy: - fail-fast: false - matrix: - flavor: - - build release - - build debug - include: - - flavor: build debug - flags: --enable-debug - artifact: -debug - - # Reduced 32-bit build uses the same boot JDK as 64-bit build - env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" - BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" - BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_FILENAME }}" - BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_URL }}" - BOOT_JDK_SHA256: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_SHA256 }}" - - steps: - - name: Checkout the source - uses: actions/checkout@v2 - with: - path: jdk - - - name: Restore boot JDK from cache - id: bootjdk - uses: actions/cache@v2 - with: - path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} - key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 - - - name: Download boot JDK - run: | - mkdir -p "${HOME}/bootjdk/${BOOT_JDK_VERSION}" - wget -O "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" "${BOOT_JDK_URL}" - echo "${BOOT_JDK_SHA256} ${HOME}/bootjdk/${BOOT_JDK_FILENAME}" | sha256sum -c >/dev/null - - tar -xf "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" -C "${HOME}/bootjdk/${BOOT_JDK_VERSION}" - mv "${HOME}/bootjdk/${BOOT_JDK_VERSION}/"*/* "${HOME}/bootjdk/${BOOT_JDK_VERSION}/" - if: steps.bootjdk.outputs.cache-hit != 'true' - - - name: Restore jtreg artifact - id: jtreg_restore - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - continue-on-error: true - - - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - if: steps.jtreg_restore.outcome == 'failure' - - - name: Checkout gtest sources - uses: actions/checkout@v2 - with: - repository: "google/googletest" - ref: "release-${{ fromJson(needs.prerequisites.outputs.dependencies).GTEST_VERSION }}" - path: gtest - - # Roll in the multilib environment and its dependencies. - # Some multilib libraries do not have proper inter-dependencies, so we have to - # install their dependencies manually. Additionally, upgrading apt solves - # the libc6 installation bugs until base image catches up, see JDK-8260460. - - name: Install dependencies - run: | - sudo dpkg --add-architecture i386 - sudo apt-get update - sudo apt-get install --only-upgrade apt - sudo apt-get install gcc-10-multilib g++-10-multilib libfreetype6-dev:i386 libxrandr-dev:i386 libxtst-dev:i386 libtiff-dev:i386 libcupsimage2-dev:i386 libcups2-dev:i386 libasound2-dev:i386 - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 - - - name: Configure - run: > - bash configure - --with-conf-name=linux-x86 - --with-target-bits=32 - ${{ matrix.flags }} - --with-version-opt=${GITHUB_ACTOR}-${GITHUB_SHA} - --with-version-build=0 - --with-boot-jdk=${HOME}/bootjdk/${BOOT_JDK_VERSION} - --with-jtreg=${HOME}/jtreg - --with-gtest=${GITHUB_WORKSPACE}/gtest - --with-default-make-target="product-bundles test-bundles" - --with-zlib=system - --enable-jtreg-failure-handler - working-directory: jdk - - - name: Build - run: make CONF_NAME=linux-x86 - working-directory: jdk - - - name: Persist test bundles - uses: actions/upload-artifact@v2 - with: - name: transient_jdk-linux-x86${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} - path: | - jdk/build/linux-x86/bundles/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin${{ matrix.artifact }}.tar.gz - jdk/build/linux-x86/bundles/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin-tests${{ matrix.artifact }}.tar.gz - - linux_x86_test: - name: Linux x86 - runs-on: "ubuntu-20.04" - needs: - - prerequisites - - linux_x86_build - - strategy: - fail-fast: false - matrix: - test: - - jdk/tier1 part 1 - - jdk/tier1 part 2 - - jdk/tier1 part 3 - - langtools/tier1 - - hs/tier1 common - - hs/tier1 compiler - - hs/tier1 gc - - hs/tier1 runtime - - hs/tier1 serviceability - include: - - test: jdk/tier1 part 1 - suites: test/jdk/:tier1_part1 - - test: jdk/tier1 part 2 - suites: test/jdk/:tier1_part2 - - test: jdk/tier1 part 3 - suites: test/jdk/:tier1_part3 - - test: langtools/tier1 - suites: test/langtools/:tier1 - - test: hs/tier1 common - suites: test/hotspot/jtreg/:tier1_common - artifact: -debug - - test: hs/tier1 compiler - suites: test/hotspot/jtreg/:tier1_compiler - artifact: -debug - - test: hs/tier1 gc - suites: test/hotspot/jtreg/:tier1_gc - artifact: -debug - - test: hs/tier1 runtime - suites: test/hotspot/jtreg/:tier1_runtime - artifact: -debug - - test: hs/tier1 serviceability - suites: test/hotspot/jtreg/:tier1_serviceability - artifact: -debug - - # Reduced 32-bit build uses the same boot JDK as 64-bit build - env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" - BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" - BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_FILENAME }}" - BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_URL }}" - BOOT_JDK_SHA256: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_SHA256 }}" - - steps: - - name: Checkout the source - uses: actions/checkout@v2 - - - name: Restore boot JDK from cache - id: bootjdk - uses: actions/cache@v2 - with: - path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} - key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 - - - name: Download boot JDK - run: | - mkdir -p "${HOME}/bootjdk/${BOOT_JDK_VERSION}" - wget -O "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" "${BOOT_JDK_URL}" - echo "${BOOT_JDK_SHA256} ${HOME}/bootjdk/${BOOT_JDK_FILENAME}" | sha256sum -c >/dev/null - - tar -xf "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" -C "${HOME}/bootjdk/${BOOT_JDK_VERSION}" - mv "${HOME}/bootjdk/${BOOT_JDK_VERSION}/"*/* "${HOME}/bootjdk/${BOOT_JDK_VERSION}/" - if: steps.bootjdk.outputs.cache-hit != 'true' - - - name: Restore jtreg artifact - id: jtreg_restore - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - continue-on-error: true - - - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - if: steps.jtreg_restore.outcome == 'failure' - - - name: Restore build artifacts - id: build_restore - uses: actions/download-artifact@v2 - with: - name: transient_jdk-linux-x86${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jdk-linux-x86${{ matrix.artifact }} - continue-on-error: true - - - name: Restore build artifacts (retry) - uses: actions/download-artifact@v2 - with: - name: transient_jdk-linux-x86${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jdk-linux-x86${{ matrix.artifact }} - if: steps.build_restore.outcome == 'failure' - - - name: Unpack jdk - run: | - mkdir -p "${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin${{ matrix.artifact }}" - tar -xf "${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin${{ matrix.artifact }}.tar.gz" -C "${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin${{ matrix.artifact }}" - - - name: Unpack tests - run: | - mkdir -p "${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin-tests${{ matrix.artifact }}" - tar -xf "${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin-tests${{ matrix.artifact }}.tar.gz" -C "${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin-tests${{ matrix.artifact }}" - - - name: Find root of jdk image dir - run: | - imageroot=`find ${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin${{ matrix.artifact }} -name release -type f` - echo "imageroot=`dirname ${imageroot}`" >> $GITHUB_ENV - - - name: Run tests - run: > - JDK_IMAGE_DIR=${{ env.imageroot }} - TEST_IMAGE_DIR=${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin-tests${{ matrix.artifact }} - BOOT_JDK=${HOME}/bootjdk/${BOOT_JDK_VERSION} - JT_HOME=${HOME}/jtreg - make test-prebuilt - CONF_NAME=run-test-prebuilt - LOG_CMDLINES=true - JTREG_VERBOSE=fail,error,time - TEST="${{ matrix.suites }}" - TEST_OPTS_JAVA_OPTIONS= - JTREG_KEYWORDS="!headful" - JTREG="JAVA_OPTIONS=-XX:-CreateCoredumpOnCrash" - - - name: Check that all tests executed successfully - if: always() - run: > - if ! grep --include=test-summary.txt -lqr build/*/test-results -e "TEST SUCCESS" ; then - cat build/*/test-results/*/text/newfailures.txt ; - exit 1 ; - fi - - - name: Create suitable test log artifact name - if: always() - run: echo "logsuffix=`echo ${{ matrix.test }} | sed -e 's!/!_!'g -e 's! !_!'g`" >> $GITHUB_ENV - - - name: Package test results - if: always() - working-directory: build/run-test-prebuilt/test-results/ - run: > - zip -r9 - "$HOME/linux-x86${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip" - . - continue-on-error: true - - - name: Package test support - if: always() - working-directory: build/run-test-prebuilt/test-support/ - run: > - zip -r9 - "$HOME/linux-x86${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip" - . - -i *.jtr - -i */hs_err*.log - -i */replay*.log - continue-on-error: true - - - name: Persist test results - if: always() - uses: actions/upload-artifact@v2 - with: - path: ~/linux-x86${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip - continue-on-error: true - - - name: Persist test outputs - if: always() - uses: actions/upload-artifact@v2 - with: - path: ~/linux-x86${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip - continue-on-error: true - - windows_x64_build: - name: Windows x64 - runs-on: "windows-2019" - needs: prerequisites - if: needs.prerequisites.outputs.should_run != 'false' && needs.prerequisites.outputs.platform_windows_x64 != 'false' - - strategy: - fail-fast: false - matrix: - flavor: - - build release - - build debug - include: - - flavor: build debug - flags: --enable-debug - artifact: -debug - - env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" - BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" - BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_FILENAME }}" - BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_URL }}" - BOOT_JDK_SHA256: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_SHA256 }}" - - steps: - - name: Restore cygwin packages from cache - id: cygwin - uses: actions/cache@v2 - with: - path: ~/cygwin/packages - key: cygwin-packages-${{ runner.os }}-v1 - - - name: Install cygwin - run: | - New-Item -Force -ItemType directory -Path "$HOME\cygwin" - & curl -L "https://www.cygwin.com/setup-x86_64.exe" -o "$HOME/cygwin/setup-x86_64.exe" - Start-Process -FilePath "$HOME\cygwin\setup-x86_64.exe" -ArgumentList "--quiet-mode --packages autoconf,make,zip,unzip --root $HOME\cygwin\cygwin64 --local-package-dir $HOME\cygwin\packages --site http://mirrors.kernel.org/sourceware/cygwin --no-desktop --no-shortcuts --no-startmenu --no-admin" -Wait -NoNewWindow - - - name: Checkout the source - uses: actions/checkout@v2 - with: - path: jdk - - - name: Restore boot JDK from cache - id: bootjdk - uses: actions/cache@v2 - with: - path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} - key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 - - - name: Download boot JDK - run: | - mkdir -p "$HOME\bootjdk\$env:BOOT_JDK_VERSION" - & curl -L "$env:BOOT_JDK_URL" -o "$HOME/bootjdk/$env:BOOT_JDK_FILENAME" - $FileHash = Get-FileHash -Algorithm SHA256 "$HOME/bootjdk/$env:BOOT_JDK_FILENAME" - $FileHash.Hash -eq $env:BOOT_JDK_SHA256 - & tar -xf "$HOME/bootjdk/$env:BOOT_JDK_FILENAME" -C "$HOME/bootjdk/$env:BOOT_JDK_VERSION" - Get-ChildItem "$HOME\bootjdk\$env:BOOT_JDK_VERSION\*\*" | Move-Item -Destination "$HOME\bootjdk\$env:BOOT_JDK_VERSION" - if: steps.bootjdk.outputs.cache-hit != 'true' - - - name: Checkout gtest sources - uses: actions/checkout@v2 - with: - repository: "google/googletest" - ref: "release-${{ fromJson(needs.prerequisites.outputs.dependencies).GTEST_VERSION }}" - path: gtest - - - name: Restore jtreg artifact - id: jtreg_restore - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - continue-on-error: true - - - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - if: steps.jtreg_restore.outcome == 'failure' - - - name: Ensure a specific version of MSVC is installed - run: > - Start-Process -FilePath 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe' -Wait -NoNewWindow -ArgumentList - 'modify --installPath "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise" --quiet - --add Microsoft.VisualStudio.Component.VC.14.28.x86.x64' - - - name: Configure - run: > - $env:Path = "$HOME\cygwin\cygwin64\bin;$HOME\cygwin\cygwin64\bin;$env:Path" ; - $env:Path = $env:Path -split ";" -match "C:\\Windows|PowerShell|cygwin" -join ";" ; - $env:BOOT_JDK = cygpath "$HOME/bootjdk/$env:BOOT_JDK_VERSION" ; - $env:JT_HOME = cygpath "$HOME/jtreg" ; - $env:GTEST = cygpath "$env:GITHUB_WORKSPACE/gtest" ; - & bash configure - --with-conf-name=windows-x64 - --with-msvc-toolset-version=14.28 - ${{ matrix.flags }} - --with-version-opt="$env:GITHUB_ACTOR-$env:GITHUB_SHA" - --with-version-build=0 - --with-boot-jdk="$env:BOOT_JDK" - --with-jtreg="$env:JT_HOME" - --with-gtest="$env:GTEST" - --with-default-make-target="product-bundles test-bundles" - --enable-jtreg-failure-handler - working-directory: jdk - - - name: Build - run: | - $env:Path = "$HOME\cygwin\cygwin64\bin;$HOME\cygwin\cygwin64\bin;$env:Path" ; - $env:Path = $env:Path -split ";" -match "C:\\Windows|PowerShell|cygwin" -join ";" ; - & make CONF_NAME=windows-x64 - working-directory: jdk - - - name: Persist test bundles - uses: actions/upload-artifact@v2 - with: - name: transient_jdk-windows-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} - path: | - jdk/build/windows-x64/bundles/jdk-${{ env.JDK_VERSION }}-internal+0_windows-x64_bin${{ matrix.artifact }}.zip - jdk/build/windows-x64/bundles/jdk-${{ env.JDK_VERSION }}-internal+0_windows-x64_bin-tests${{ matrix.artifact }}.tar.gz - jdk/build/windows-x64/bundles/jdk-${{ env.JDK_VERSION }}-internal+0_windows-x64_bin${{ matrix.artifact }}-symbols.tar.gz - - windows_x64_test: - name: Windows x64 - runs-on: "windows-2019" - needs: - - prerequisites - - windows_x64_build - - strategy: - fail-fast: false - matrix: - test: - - jdk/tier1 part 1 - - jdk/tier1 part 2 - - jdk/tier1 part 3 - - langtools/tier1 - - hs/tier1 common - - hs/tier1 compiler - - hs/tier1 gc - - hs/tier1 runtime - - hs/tier1 serviceability - include: - - test: jdk/tier1 part 1 - suites: test/jdk/:tier1_part1 - - test: jdk/tier1 part 2 - suites: test/jdk/:tier1_part2 - - test: jdk/tier1 part 3 - suites: test/jdk/:tier1_part3 - - test: langtools/tier1 - suites: test/langtools/:tier1 - - test: hs/tier1 common - suites: test/hotspot/jtreg/:tier1_common - artifact: -debug - - test: hs/tier1 compiler - suites: test/hotspot/jtreg/:tier1_compiler - artifact: -debug - - test: hs/tier1 gc - suites: test/hotspot/jtreg/:tier1_gc - artifact: -debug - - test: hs/tier1 runtime - suites: test/hotspot/jtreg/:tier1_runtime - artifact: -debug - - test: hs/tier1 serviceability - suites: test/hotspot/jtreg/:tier1_serviceability - artifact: -debug - - env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" - BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" - BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_FILENAME }}" - BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_URL }}" - BOOT_JDK_SHA256: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_SHA256 }}" - - steps: - - name: Checkout the source - uses: actions/checkout@v2 - - - name: Restore boot JDK from cache - id: bootjdk - uses: actions/cache@v2 - with: - path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} - key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 - - - name: Download boot JDK - run: | - mkdir -p "$HOME\bootjdk\$env:BOOT_JDK_VERSION" - & curl -L "$env:BOOT_JDK_URL" -o "$HOME/bootjdk/$env:BOOT_JDK_FILENAME" - $FileHash = Get-FileHash -Algorithm SHA256 "$HOME/bootjdk/$env:BOOT_JDK_FILENAME" - $FileHash.Hash -eq $env:BOOT_JDK_SHA256 - & tar -xf "$HOME/bootjdk/$env:BOOT_JDK_FILENAME" -C "$HOME/bootjdk/$env:BOOT_JDK_VERSION" - Get-ChildItem "$HOME\bootjdk\$env:BOOT_JDK_VERSION\*\*" | Move-Item -Destination "$HOME\bootjdk\$env:BOOT_JDK_VERSION" - if: steps.bootjdk.outputs.cache-hit != 'true' - - - name: Restore cygwin packages from cache - id: cygwin - uses: actions/cache@v2 - with: - path: ~/cygwin/packages - key: cygwin-packages-${{ runner.os }}-v1 - - - name: Install cygwin - run: | - New-Item -Force -ItemType directory -Path "$HOME\cygwin" - & curl -L "https://www.cygwin.com/setup-x86_64.exe" -o "$HOME/cygwin/setup-x86_64.exe" - Start-Process -FilePath "$HOME\cygwin\setup-x86_64.exe" -ArgumentList "--quiet-mode --packages autoconf,make,zip,unzip --root $HOME\cygwin\cygwin64 --local-package-dir $HOME\cygwin\packages --site http://mirrors.kernel.org/sourceware/cygwin --no-desktop --no-shortcuts --no-startmenu --no-admin" -Wait -NoNewWindow - - - name: Restore jtreg artifact - id: jtreg_restore - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - continue-on-error: true - - - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - if: steps.jtreg_restore.outcome == 'failure' - - - name: Restore build artifacts - id: build_restore - uses: actions/download-artifact@v2 - with: - name: transient_jdk-windows-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jdk-windows-x64${{ matrix.artifact }} - continue-on-error: true - - - name: Restore build artifacts (retry) - uses: actions/download-artifact@v2 - with: - name: transient_jdk-windows-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jdk-windows-x64${{ matrix.artifact }} - if: steps.build_restore.outcome == 'failure' - - - name: Unpack jdk - run: | - mkdir -p "${HOME}/jdk-windows-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_windows-x64_bin${{ matrix.artifact }}" - tar -xf "${HOME}/jdk-windows-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_windows-x64_bin${{ matrix.artifact }}.zip" -C "${HOME}/jdk-windows-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_windows-x64_bin${{ matrix.artifact }}" - - - name: Unpack symbols - run: | - mkdir -p "${HOME}/jdk-windows-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_windows-x64_bin${{ matrix.artifact }}-symbols" - tar -xf "${HOME}/jdk-windows-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_windows-x64_bin${{ matrix.artifact }}-symbols.tar.gz" -C "${HOME}/jdk-windows-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_windows-x64_bin${{ matrix.artifact }}-symbols" - - - name: Unpack tests - run: | - mkdir -p "${HOME}/jdk-windows-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_windows-x64_bin-tests${{ matrix.artifact }}" - tar -xf "${HOME}/jdk-windows-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_windows-x64_bin-tests${{ matrix.artifact }}.tar.gz" -C "${HOME}/jdk-windows-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_windows-x64_bin-tests${{ matrix.artifact }}" - - - name: Find root of jdk image dir - run: echo ("imageroot=" + (Get-ChildItem -Path $HOME/jdk-windows-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_windows-x64_bin${{ matrix.artifact }} -Filter release -Recurse -ErrorAction SilentlyContinue -Force).DirectoryName) | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 - - - name: Run tests - run: > - $env:Path = "$HOME\cygwin\cygwin64\bin;$HOME\cygwin\cygwin64\bin;$env:Path" ; - $env:Path = $env:Path -split ";" -match "C:\\Windows|PowerShell|cygwin" -join ";" ; - $env:JDK_IMAGE_DIR = cygpath "${{ env.imageroot }}" ; - $env:SYMBOLS_IMAGE_DIR = cygpath "${{ env.imageroot }}" ; - $env:TEST_IMAGE_DIR = cygpath "$HOME/jdk-windows-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_windows-x64_bin-tests${{ matrix.artifact }}" ; - $env:BOOT_JDK = cygpath "$HOME/bootjdk/$env:BOOT_JDK_VERSION" ; - $env:JT_HOME = cygpath "$HOME/jtreg" ; - & make test-prebuilt - CONF_NAME=run-test-prebuilt - LOG_CMDLINES=true - JTREG_VERBOSE=fail,error,time - TEST=${{ matrix.suites }} - TEST_OPTS_JAVA_OPTIONS= - JTREG_KEYWORDS="!headful" - JTREG="JAVA_OPTIONS=-XX:-CreateCoredumpOnCrash" - - - name: Check that all tests executed successfully - if: always() - run: > - if ((Get-ChildItem -Path build\*\test-results\test-summary.txt -Recurse | Select-String -Pattern "TEST SUCCESS" ).Count -eq 0) { - Get-Content -Path build\*\test-results\*\*\newfailures.txt ; - exit 1 - } - - - name: Create suitable test log artifact name - if: always() - run: echo ("logsuffix=" + ("${{ matrix.test }}" -replace "/", "_" -replace " ", "_")) | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 - - - name: Package test results - if: always() - working-directory: build/run-test-prebuilt/test-results/ - run: > - $env:Path = "$HOME\cygwin\cygwin64\bin;$env:Path" ; - zip -r9 - "$HOME/windows-x64${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip" - . - continue-on-error: true - - - name: Package test support - if: always() - working-directory: build/run-test-prebuilt/test-support/ - run: > - $env:Path = "$HOME\cygwin\cygwin64\bin;$env:Path" ; - zip -r9 - "$HOME/windows-x64${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip" - . - -i *.jtr - -i */hs_err*.log - -i */replay*.log - continue-on-error: true - - - name: Persist test results - if: always() - uses: actions/upload-artifact@v2 - with: - path: ~/windows-x64${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip - continue-on-error: true - - - name: Persist test outputs - if: always() - uses: actions/upload-artifact@v2 - with: - path: ~/windows-x64${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip - continue-on-error: true - - macos_x64_build: - name: macOS x64 - runs-on: "macos-10.15" - needs: prerequisites - if: needs.prerequisites.outputs.should_run != 'false' && needs.prerequisites.outputs.platform_macos_x64 != 'false' - - strategy: - fail-fast: false - matrix: - flavor: - - build release - - build debug - include: - - flavor: build release - - flavor: build debug - flags: --enable-debug - artifact: -debug - - env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" - BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" - BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_FILENAME }}" - BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_URL }}" - BOOT_JDK_SHA256: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_SHA256 }}" - - steps: - - name: Checkout the source - uses: actions/checkout@v2 - with: - path: jdk - - - name: Restore boot JDK from cache - id: bootjdk - uses: actions/cache@v2 - with: - path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} - key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 - - - name: Download boot JDK - run: | - mkdir -p ${HOME}/bootjdk/${BOOT_JDK_VERSION} || true - wget -O "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" "${BOOT_JDK_URL}" - echo "${BOOT_JDK_SHA256} ${HOME}/bootjdk/${BOOT_JDK_FILENAME}" | shasum -a 256 -c >/dev/null - - tar -xf "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" -C "${HOME}/bootjdk/${BOOT_JDK_VERSION}" - mv "${HOME}/bootjdk/${BOOT_JDK_VERSION}/"*/* "${HOME}/bootjdk/${BOOT_JDK_VERSION}/" - if: steps.bootjdk.outputs.cache-hit != 'true' - - - name: Restore jtreg artifact - id: jtreg_restore - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - continue-on-error: true - - - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - if: steps.jtreg_restore.outcome == 'failure' - - - name: Checkout gtest sources - uses: actions/checkout@v2 - with: - repository: "google/googletest" - ref: "release-${{ fromJson(needs.prerequisites.outputs.dependencies).GTEST_VERSION }}" - path: gtest - - - name: Install dependencies - run: brew install make - - - name: Select Xcode version - run: sudo xcode-select --switch /Applications/Xcode_11.3.1.app/Contents/Developer - - - name: Configure - run: > - bash configure - --with-conf-name=macos-x64 - ${{ matrix.flags }} - --with-version-opt=${GITHUB_ACTOR}-${GITHUB_SHA} - --with-version-build=0 - --with-boot-jdk=${HOME}/bootjdk/${BOOT_JDK_VERSION}/Contents/Home - --with-jtreg=${HOME}/jtreg - --with-gtest=${GITHUB_WORKSPACE}/gtest - --with-default-make-target="product-bundles test-bundles" - --with-zlib=system - --enable-jtreg-failure-handler - working-directory: jdk - - - name: Build - run: make CONF_NAME=macos-x64 - working-directory: jdk - - - name: Persist test bundles - uses: actions/upload-artifact@v2 - with: - name: transient_jdk-macos-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} - path: | - jdk/build/macos-x64/bundles/jdk-${{ env.JDK_VERSION }}-internal+0_macos-x64_bin${{ matrix.artifact }}.tar.gz - jdk/build/macos-x64/bundles/jdk-${{ env.JDK_VERSION }}-internal+0_macos-x64_bin-tests${{ matrix.artifact }}.tar.gz - - macos_aarch64_build: - name: macOS aarch64 - runs-on: "macos-10.15" - needs: prerequisites - if: needs.prerequisites.outputs.should_run != 'false' && needs.prerequisites.outputs.platform_macos_aarch64 != 'false' - - strategy: - fail-fast: false - matrix: - flavor: - - build release - - build debug - include: - - flavor: build release - - flavor: build debug - flags: --enable-debug - artifact: -debug - - env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" - BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" - BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_FILENAME }}" - BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_URL }}" - BOOT_JDK_SHA256: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_SHA256 }}" - - steps: - - name: Checkout the source - uses: actions/checkout@v2 - with: - path: jdk - - - name: Restore boot JDK from cache - id: bootjdk - uses: actions/cache@v2 - with: - path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} - key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 - - - name: Download boot JDK - run: | - mkdir -p ${HOME}/bootjdk/${BOOT_JDK_VERSION} || true - wget -O "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" "${BOOT_JDK_URL}" - echo "${BOOT_JDK_SHA256} ${HOME}/bootjdk/${BOOT_JDK_FILENAME}" | shasum -a 256 -c >/dev/null - - tar -xf "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" -C "${HOME}/bootjdk/${BOOT_JDK_VERSION}" - mv "${HOME}/bootjdk/${BOOT_JDK_VERSION}/"*/* "${HOME}/bootjdk/${BOOT_JDK_VERSION}/" - if: steps.bootjdk.outputs.cache-hit != 'true' - - - name: Restore jtreg artifact - id: jtreg_restore - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - continue-on-error: true - - - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - if: steps.jtreg_restore.outcome == 'failure' - - - name: Checkout gtest sources - uses: actions/checkout@v2 - with: - repository: "google/googletest" - ref: "release-${{ fromJson(needs.prerequisites.outputs.dependencies).GTEST_VERSION }}" - path: gtest - - - name: Install dependencies - run: brew install make - - - name: Select Xcode version - run: sudo xcode-select --switch /Applications/Xcode_12.4.app/Contents/Developer - - - name: Configure - run: > - bash configure - --with-conf-name=macos-aarch64 - --openjdk-target=aarch64-apple-darwin - ${{ matrix.flags }} - --with-version-opt=${GITHUB_ACTOR}-${GITHUB_SHA} - --with-version-build=0 - --with-boot-jdk=${HOME}/bootjdk/${BOOT_JDK_VERSION}/Contents/Home - --with-jtreg=${HOME}/jtreg - --with-gtest=${GITHUB_WORKSPACE}/gtest - --with-default-make-target="product-bundles test-bundles" - --with-zlib=system - --enable-jtreg-failure-handler - working-directory: jdk - - - name: Build - run: make CONF_NAME=macos-aarch64 - working-directory: jdk - - - name: Persist test bundles - uses: actions/upload-artifact@v2 - with: - name: transient_jdk-macos-aarch64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} - path: | - jdk/build/macos-aarch64/bundles/jdk-${{ env.JDK_VERSION }}-internal+0_macos-aarch64_bin${{ matrix.artifact }}.tar.gz - jdk/build/macos-aarch64/bundles/jdk-${{ env.JDK_VERSION }}-internal+0_macos-aarch64_bin-tests${{ matrix.artifact }}.tar.gz - - - macos_x64_test: - name: macOS x64 - runs-on: "macos-10.15" - needs: - - prerequisites - - macos_x64_build - - strategy: - fail-fast: false - matrix: - test: - - jdk/tier1 part 1 - - jdk/tier1 part 2 - - jdk/tier1 part 3 - - langtools/tier1 - - hs/tier1 common - - hs/tier1 compiler - - hs/tier1 gc - - hs/tier1 runtime - - hs/tier1 serviceability - include: - - test: jdk/tier1 part 1 - suites: test/jdk/:tier1_part1 - - test: jdk/tier1 part 2 - suites: test/jdk/:tier1_part2 - - test: jdk/tier1 part 3 - suites: test/jdk/:tier1_part3 - - test: langtools/tier1 - suites: test/langtools/:tier1 - - test: hs/tier1 common - suites: test/hotspot/jtreg/:tier1_common - artifact: -debug - - test: hs/tier1 compiler - suites: test/hotspot/jtreg/:tier1_compiler - artifact: -debug - - test: hs/tier1 gc - suites: test/hotspot/jtreg/:tier1_gc - artifact: -debug - - test: hs/tier1 runtime - suites: test/hotspot/jtreg/:tier1_runtime - artifact: -debug - - test: hs/tier1 serviceability - suites: test/hotspot/jtreg/:tier1_serviceability - artifact: -debug - - env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" - BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" - BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_FILENAME }}" - BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_URL }}" - BOOT_JDK_SHA256: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_SHA256 }}" - - steps: - - name: Checkout the source - uses: actions/checkout@v2 - - - name: Restore boot JDK from cache - id: bootjdk - uses: actions/cache@v2 - with: - path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} - key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 - - - name: Download boot JDK - run: | - mkdir -p ${HOME}/bootjdk/${BOOT_JDK_VERSION} || true - wget -O "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" "${BOOT_JDK_URL}" - echo "${BOOT_JDK_SHA256} ${HOME}/bootjdk/${BOOT_JDK_FILENAME}" | shasum -a 256 -c >/dev/null - - tar -xf "${HOME}/bootjdk/${BOOT_JDK_FILENAME}" -C "${HOME}/bootjdk/${BOOT_JDK_VERSION}" - mv "${HOME}/bootjdk/${BOOT_JDK_VERSION}/"*/* "${HOME}/bootjdk/${BOOT_JDK_VERSION}/" - if: steps.bootjdk.outputs.cache-hit != 'true' - - - name: Restore jtreg artifact - id: jtreg_restore - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - continue-on-error: true - - - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 - with: - name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jtreg/ - if: steps.jtreg_restore.outcome == 'failure' - - - name: Restore build artifacts - id: build_restore - uses: actions/download-artifact@v2 - with: - name: transient_jdk-macos-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jdk-macos-x64${{ matrix.artifact }} - continue-on-error: true - - - name: Restore build artifacts (retry) - uses: actions/download-artifact@v2 - with: - name: transient_jdk-macos-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} - path: ~/jdk-macos-x64${{ matrix.artifact }} - if: steps.build_restore.outcome == 'failure' - - - name: Unpack jdk - run: | - mkdir -p "${HOME}/jdk-macos-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_macos-x64_bin${{ matrix.artifact }}" - tar -xf "${HOME}/jdk-macos-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_macos-x64_bin${{ matrix.artifact }}.tar.gz" -C "${HOME}/jdk-macos-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_macos-x64_bin${{ matrix.artifact }}" - - - name: Unpack tests - run: | - mkdir -p "${HOME}/jdk-macos-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_macos-x64_bin-tests${{ matrix.artifact }}" - tar -xf "${HOME}/jdk-macos-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_macos-x64_bin-tests${{ matrix.artifact }}.tar.gz" -C "${HOME}/jdk-macos-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_macos-x64_bin-tests${{ matrix.artifact }}" - - - name: Install dependencies - run: brew install make - - - name: Select Xcode version - run: sudo xcode-select --switch /Applications/Xcode_11.3.1.app/Contents/Developer - - - name: Find root of jdk image dir - run: | - imageroot=`find ${HOME}/jdk-macos-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_macos-x64_bin${{ matrix.artifact }} -name release -type f` - echo "imageroot=`dirname ${imageroot}`" >> $GITHUB_ENV - - - name: Run tests - run: > - JDK_IMAGE_DIR=${{ env.imageroot }} - TEST_IMAGE_DIR=${HOME}/jdk-macos-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_macos-x64_bin-tests${{ matrix.artifact }} - BOOT_JDK=${HOME}/bootjdk/${BOOT_JDK_VERSION}/Contents/Home - JT_HOME=${HOME}/jtreg - gmake test-prebuilt - CONF_NAME=run-test-prebuilt - LOG_CMDLINES=true - JTREG_VERBOSE=fail,error,time - TEST=${{ matrix.suites }} - TEST_OPTS_JAVA_OPTIONS= - JTREG_KEYWORDS="!headful" - JTREG="JAVA_OPTIONS=-XX:-CreateCoredumpOnCrash" - - - name: Check that all tests executed successfully - if: always() - run: > - if ! grep --include=test-summary.txt -lqr build/*/test-results -e "TEST SUCCESS" ; then - cat build/*/test-results/*/text/newfailures.txt ; - exit 1 ; - fi - - - name: Create suitable test log artifact name - if: always() - run: echo "logsuffix=`echo ${{ matrix.test }} | sed -e 's!/!_!'g -e 's! !_!'g`" >> $GITHUB_ENV - - - name: Package test results - if: always() - working-directory: build/run-test-prebuilt/test-results/ - run: > - zip -r9 - "$HOME/macos-x64${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip" - . - continue-on-error: true - - - name: Package test support - if: always() - working-directory: build/run-test-prebuilt/test-support/ - run: > - zip -r9 - "$HOME/macos-x64${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip" - . - -i *.jtr - -i */hs_err*.log - -i */replay*.log - continue-on-error: true - - - name: Persist test results - if: always() - uses: actions/upload-artifact@v2 - with: - path: ~/macos-x64${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip - continue-on-error: true - - - name: Persist test outputs - if: always() - uses: actions/upload-artifact@v2 - with: - path: ~/macos-x64${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip - continue-on-error: true - - artifacts: - name: Post-process artifacts - runs-on: "ubuntu-20.04" - if: always() - continue-on-error: true - needs: - - prerequisites - - linux_additional_build - - linux_x64_test - - linux_x86_test - - windows_x64_test - - macos_x64_test - - macos_aarch64_build - - steps: - - name: Determine current artifacts endpoint - id: actions_runtime - uses: actions/github-script@v3 - with: - script: "return { url: process.env['ACTIONS_RUNTIME_URL'], token: process.env['ACTIONS_RUNTIME_TOKEN'] }" - - - name: Display current artifacts - run: > - curl -s -H 'Accept: application/json;api-version=6.0-preview' - -H 'Authorization: Bearer ${{ fromJson(steps.actions_runtime.outputs.result).token }}' - '${{ fromJson(steps.actions_runtime.outputs.result).url }}_apis/pipelines/workflows/${{ github.run_id }}/artifacts?api-version=6.0-preview' - - - name: Delete transient artifacts - run: > - for url in ` - curl -s -H 'Accept: application/json;api-version=6.0-preview' - -H 'Authorization: Bearer ${{ fromJson(steps.actions_runtime.outputs.result).token }}' - '${{ fromJson(steps.actions_runtime.outputs.result).url }}_apis/pipelines/workflows/${{ github.run_id }}/artifacts?api-version=6.0-preview' | - jq -r -c '.value | map(select(.name|startswith("transient_"))) | .[].url'`; do - curl -s -H 'Accept: application/json;api-version=6.0-preview' - -H 'Authorization: Bearer ${{ fromJson(steps.actions_runtime.outputs.result).token }}' - -X DELETE "${url}"; - done - - - name: Fetch remaining artifacts (test results) - uses: actions/download-artifact@v2 - with: - path: test-results - - - name: Delete remaining artifacts - run: > - for url in ` - curl -s -H 'Accept: application/json;api-version=6.0-preview' - -H 'Authorization: Bearer ${{ fromJson(steps.actions_runtime.outputs.result).token }}' - '${{ fromJson(steps.actions_runtime.outputs.result).url }}_apis/pipelines/workflows/${{ github.run_id }}/artifacts?api-version=6.0-preview' | - jq -r -c '.value | .[].url'`; do - curl -s -H 'Accept: application/json;api-version=6.0-preview' - -H 'Authorization: Bearer ${{ fromJson(steps.actions_runtime.outputs.result).token }}' - -X DELETE "${url}"; - done - - - name: Upload a combined test results artifact - uses: actions/upload-artifact@v2 - with: - name: test-results_${{ needs.prerequisites.outputs.bundle_id }} - path: test-results From 2a5380ebe75fbfc4a26169a682f0418694aa6d50 Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Tue, 10 Dec 2024 20:56:35 -0500 Subject: [PATCH 02/82] Disable jdk17u merging CI job --- azure-pipelines.yml | 146 ++++++++++++++++++++++---------------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 9784c3888e0..b20175a8236 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -27,79 +27,79 @@ jobs: # - bash: make -C /jdk run-test-tier1 # displayName: make run-test-tier1 -- job: build_jdk17u - pool: - vmImage: 'ubuntu-latest' - container: wmdietl/cf-ubuntu-jdk17-plus:latest - timeoutInMinutes: 0 - steps: - - bash: | - whoami - git config --get remote.origin.url - pwd - ls -al - env | sort - displayName: show environment - - bash: | - set -ex - if [ -d /tmp/$USER/git-scripts ]; \ - then git -C /tmp/$USER/git-scripts pull -q > /dev/null 2>&1 ; \ - else mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/eisop-plume-lib/git-scripts.git ; \ - fi - displayName: git-scripts - - bash: | - set -ex - if [ -d /tmp/$USER/plume-scripts ]; \ - then git -C /tmp/$USER/plume-scripts pull -q > /dev/null 2>&1 ; \ - else mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/eisop-plume-lib/plume-scripts.git ; \ - fi - displayName: plume-scripts - # This creates ../jdk17u . - # If the depth is too small, the merge will fail. However, we cannot use "--filter=blob:none" - # because that leads to "fatal: remote error: filter 'combine' not supported". - - bash: | - set -ex - pwd - ls -al .. || true - ls -al ../jdk17u || true - df . - /tmp/$USER/git-scripts/git-clone-related typetools jdk17u ../jdk17u --depth 999 - git config --global user.email "you@example.com" - git config --global user.name "Your Name" - git config --global core.longpaths true - git config --global core.protectNTFS false - cd ../jdk17u && git status - git diff --exit-code - echo $? - displayName: clone-related-jdk17u - - bash: | - set -ex - git config --global user.email "you@example.com" - git config --global user.name "Your Name" - git config --global pull.ff true - git config --global pull.rebase false - git config --global core.longpaths true - git config --global core.protectNTFS false - eval `/tmp/$USER/plume-scripts/ci-info eisop` - cd ../jdk17u && git status - echo "About to run: git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH}" - cd ../jdk17u && git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH} || (git --version && git show && git status && echo "Merge failed; see 'Pull request merge conflicts' at https://github.com/eisop/jdk/blob/master/README.md" && false) - displayName: git merge - - bash: cd ../jdk17u && export JT_HOME=/usr/share/jtreg && bash ./configure --with-jtreg=/usr/share/jtreg --disable-warnings-as-errors - displayName: configure - - bash: cd ../jdk17u && make jdk - displayName: make jdk - ## This works only after `make images` - # - bash: cd ../jdk17u && build/*/images/jdk/bin/java -version - # displayName: version - # - bash: make -C /jdk17u run-test-tier1 - # timeoutInMinutes: 0 - # displayName: make run-test-tier1 - # - bash: make -C /jdk17u :test/jdk:tier1 - ## Temporarily comment out because of trouble finding junit and jasm - # - bash: cd ../jdk17u && make run-test TEST="jtreg:test/jdk:tier1" - # timeoutInMinutes: 0 - # displayName: make run-test +# - job: build_jdk17u +# pool: +# vmImage: 'ubuntu-latest' +# container: wmdietl/cf-ubuntu-jdk17-plus:latest +# timeoutInMinutes: 0 +# steps: +# - bash: | +# whoami +# git config --get remote.origin.url +# pwd +# ls -al +# env | sort +# displayName: show environment +# - bash: | +# set -ex +# if [ -d /tmp/$USER/git-scripts ]; \ +# then git -C /tmp/$USER/git-scripts pull -q > /dev/null 2>&1 ; \ +# else mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/eisop-plume-lib/git-scripts.git ; \ +# fi +# displayName: git-scripts +# - bash: | +# set -ex +# if [ -d /tmp/$USER/plume-scripts ]; \ +# then git -C /tmp/$USER/plume-scripts pull -q > /dev/null 2>&1 ; \ +# else mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/eisop-plume-lib/plume-scripts.git ; \ +# fi +# displayName: plume-scripts +# # This creates ../jdk17u . +# # If the depth is too small, the merge will fail. However, we cannot use "--filter=blob:none" +# # because that leads to "fatal: remote error: filter 'combine' not supported". +# - bash: | +# set -ex +# pwd +# ls -al .. || true +# ls -al ../jdk17u || true +# df . +# /tmp/$USER/git-scripts/git-clone-related typetools jdk17u ../jdk17u --depth 999 +# git config --global user.email "you@example.com" +# git config --global user.name "Your Name" +# git config --global core.longpaths true +# git config --global core.protectNTFS false +# cd ../jdk17u && git status +# git diff --exit-code +# echo $? +# displayName: clone-related-jdk17u +# - bash: | +# set -ex +# git config --global user.email "you@example.com" +# git config --global user.name "Your Name" +# git config --global pull.ff true +# git config --global pull.rebase false +# git config --global core.longpaths true +# git config --global core.protectNTFS false +# eval `/tmp/$USER/plume-scripts/ci-info eisop` +# cd ../jdk17u && git status +# echo "About to run: git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH}" +# cd ../jdk17u && git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH} || (git --version && git show && git status && echo "Merge failed; see 'Pull request merge conflicts' at https://github.com/eisop/jdk/blob/master/README.md" && false) +# displayName: git merge +# - bash: cd ../jdk17u && export JT_HOME=/usr/share/jtreg && bash ./configure --with-jtreg=/usr/share/jtreg --disable-warnings-as-errors +# displayName: configure +# - bash: cd ../jdk17u && make jdk +# displayName: make jdk +# ## This works only after `make images` +# # - bash: cd ../jdk17u && build/*/images/jdk/bin/java -version +# # displayName: version +# # - bash: make -C /jdk17u run-test-tier1 +# # timeoutInMinutes: 0 +# # displayName: make run-test-tier1 +# # - bash: make -C /jdk17u :test/jdk:tier1 +# ## Temporarily comment out because of trouble finding junit and jasm +# # - bash: cd ../jdk17u && make run-test TEST="jtreg:test/jdk:tier1" +# # timeoutInMinutes: 0 +# # displayName: make run-test - job: test_cftests_all_jdk8 timeoutInMinutes: 105 From ecbfa4a062cc984424e6dcc17ea926389f93b34d Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 2 Jan 2025 07:56:50 -0800 Subject: [PATCH 03/82] Use `@SqlEvenQuotes` annotations from the JDK, not `.astub` file --- .../share/classes/java/sql/Connection.java | 21 +++++++------- .../share/classes/java/sql/Statement.java | 29 ++++++++++--------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/java.sql/share/classes/java/sql/Connection.java b/src/java.sql/share/classes/java/sql/Connection.java index b1f0f5930ea..ca4614e1153 100644 --- a/src/java.sql/share/classes/java/sql/Connection.java +++ b/src/java.sql/share/classes/java/sql/Connection.java @@ -26,6 +26,7 @@ package java.sql; import org.checkerframework.checker.mustcall.qual.InheritableMustCall; +import org.checkerframework.checker.sqlquotes.qual.SqlEvenQuotes; import org.checkerframework.framework.qual.AnnotatedFor; import java.util.Properties; @@ -141,7 +142,7 @@ public interface Connection extends Wrapper, AutoCloseable { * @throws SQLException if a database access error occurs * or this method is called on a closed connection */ - PreparedStatement prepareStatement(String sql) + PreparedStatement prepareStatement(@SqlEvenQuotes String sql) throws SQLException; /** @@ -174,7 +175,7 @@ PreparedStatement prepareStatement(String sql) * @throws SQLException if a database access error occurs * or this method is called on a closed connection */ - CallableStatement prepareCall(String sql) throws SQLException; + CallableStatement prepareCall(@SqlEvenQuotes String sql) throws SQLException; /** * Converts the given SQL statement into the system's native SQL grammar. @@ -188,7 +189,7 @@ PreparedStatement prepareStatement(String sql) * @throws SQLException if a database access error occurs * or this method is called on a closed connection */ - String nativeSQL(String sql) throws SQLException; + String nativeSQL(@SqlEvenQuotes String sql) throws SQLException; /** * Sets this connection's auto-commit mode to the given state. @@ -569,7 +570,7 @@ Statement createStatement(int resultSetType, int resultSetConcurrency) * set type and result set concurrency. * @since 1.2 */ - PreparedStatement prepareStatement(String sql, int resultSetType, + PreparedStatement prepareStatement(@SqlEvenQuotes String sql, int resultSetType, int resultSetConcurrency) throws SQLException; @@ -603,7 +604,7 @@ PreparedStatement prepareStatement(String sql, int resultSetType, * set type and result set concurrency. * @since 1.2 */ - CallableStatement prepareCall(String sql, int resultSetType, + CallableStatement prepareCall(@SqlEvenQuotes String sql, int resultSetType, int resultSetConcurrency) throws SQLException; /** @@ -855,7 +856,7 @@ Statement createStatement(int resultSetType, int resultSetConcurrency, * @see ResultSet * @since 1.4 */ - PreparedStatement prepareStatement(String sql, int resultSetType, + PreparedStatement prepareStatement(@SqlEvenQuotes String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException; @@ -895,7 +896,7 @@ PreparedStatement prepareStatement(String sql, int resultSetType, * @see ResultSet * @since 1.4 */ - CallableStatement prepareCall(String sql, int resultSetType, + CallableStatement prepareCall(@SqlEvenQuotes String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException; @@ -942,7 +943,7 @@ CallableStatement prepareCall(String sql, int resultSetType, * this method with a constant of Statement.RETURN_GENERATED_KEYS * @since 1.4 */ - PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) + PreparedStatement prepareStatement(@SqlEvenQuotes String sql, int autoGeneratedKeys) throws SQLException; /** @@ -990,7 +991,7 @@ PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) * * @since 1.4 */ - PreparedStatement prepareStatement(String sql, int columnIndexes[]) + PreparedStatement prepareStatement(@SqlEvenQuotes String sql, int columnIndexes[]) throws SQLException; /** @@ -1038,7 +1039,7 @@ PreparedStatement prepareStatement(String sql, int columnIndexes[]) * * @since 1.4 */ - PreparedStatement prepareStatement(String sql, String columnNames[]) + PreparedStatement prepareStatement(@SqlEvenQuotes String sql, String columnNames[]) throws SQLException; /** diff --git a/src/java.sql/share/classes/java/sql/Statement.java b/src/java.sql/share/classes/java/sql/Statement.java index 500a6b68ebe..41a15595553 100644 --- a/src/java.sql/share/classes/java/sql/Statement.java +++ b/src/java.sql/share/classes/java/sql/Statement.java @@ -25,6 +25,7 @@ package java.sql; +import org.checkerframework.checker.sqlquotes.qual.SqlEvenQuotes; import org.checkerframework.checker.tainting.qual.Untainted; import java.util.regex.Pattern; @@ -68,7 +69,7 @@ public interface Statement extends Wrapper, AutoCloseable { * method has been exceeded and has at least attempted to cancel * the currently running {@code Statement} */ - ResultSet executeQuery(@Untainted String sql) throws SQLException; + ResultSet executeQuery(@Untainted @SqlEvenQuotes @SqlEvenQuotes String sql) throws SQLException; /** * Executes the given SQL statement, which may be an {@code INSERT}, @@ -93,7 +94,7 @@ public interface Statement extends Wrapper, AutoCloseable { * method has been exceeded and has at least attempted to cancel * the currently running {@code Statement} */ - int executeUpdate(@Untainted String sql) throws SQLException; + int executeUpdate(@Untainted @SqlEvenQuotes String sql) throws SQLException; /** * Releases this {@code Statement} object's database @@ -357,7 +358,7 @@ public interface Statement extends Wrapper, AutoCloseable { * @see #getUpdateCount * @see #getMoreResults */ - boolean execute(@Untainted String sql) throws SQLException; + boolean execute(@Untainted @SqlEvenQuotes String sql) throws SQLException; /** * Retrieves the current result as a {@code ResultSet} object. @@ -523,7 +524,7 @@ public interface Statement extends Wrapper, AutoCloseable { * @see DatabaseMetaData#supportsBatchUpdates * @since 1.2 */ - void addBatch( @Untainted String sql ) throws SQLException; + void addBatch( @Untainted @SqlEvenQuotes String sql ) throws SQLException; /** * Empties this {@code Statement} object's current list of @@ -757,7 +758,7 @@ public interface Statement extends Wrapper, AutoCloseable { * the currently running {@code Statement} * @since 1.4 */ - int executeUpdate(@Untainted String sql, int autoGeneratedKeys) throws SQLException; + int executeUpdate(@Untainted @SqlEvenQuotes String sql, int autoGeneratedKeys) throws SQLException; /** * Executes the given SQL statement and signals the driver that the @@ -792,7 +793,7 @@ public interface Statement extends Wrapper, AutoCloseable { * the currently running {@code Statement} * @since 1.4 */ - int executeUpdate(@Untainted String sql, int columnIndexes[]) throws SQLException; + int executeUpdate(@Untainted @SqlEvenQuotes String sql, int columnIndexes[]) throws SQLException; /** * Executes the given SQL statement and signals the driver that the @@ -826,7 +827,7 @@ public interface Statement extends Wrapper, AutoCloseable { * the currently running {@code Statement} * @since 1.4 */ - int executeUpdate(@Untainted String sql, String columnNames[]) throws SQLException; + int executeUpdate(@Untainted @SqlEvenQuotes String sql, String columnNames[]) throws SQLException; /** * Executes the given SQL statement, which may return multiple results, @@ -879,7 +880,7 @@ public interface Statement extends Wrapper, AutoCloseable { * * @since 1.4 */ - boolean execute(@Untainted String sql, int autoGeneratedKeys) throws SQLException; + boolean execute(@Untainted @SqlEvenQuotes String sql, int autoGeneratedKeys) throws SQLException; /** * Executes the given SQL statement, which may return multiple results, @@ -928,7 +929,7 @@ public interface Statement extends Wrapper, AutoCloseable { * * @since 1.4 */ - boolean execute(@Untainted String sql, int columnIndexes[]) throws SQLException; + boolean execute(@Untainted @SqlEvenQuotes String sql, int columnIndexes[]) throws SQLException; /** * Executes the given SQL statement, which may return multiple results, @@ -978,7 +979,7 @@ public interface Statement extends Wrapper, AutoCloseable { * * @since 1.4 */ - boolean execute(@Untainted String sql, String columnNames[]) throws SQLException; + boolean execute(@Untainted @SqlEvenQuotes String sql, String columnNames[]) throws SQLException; /** * Retrieves the result set holdability for {@code ResultSet} objects @@ -1234,7 +1235,7 @@ default long[] executeLargeBatch() throws SQLException { * the currently running {@code Statement} * @since 1.8 */ - default long executeLargeUpdate(@Untainted String sql) throws SQLException { + default long executeLargeUpdate(@Untainted @SqlEvenQuotes String sql) throws SQLException { throw new UnsupportedOperationException("executeLargeUpdate not implemented"); } @@ -1281,7 +1282,7 @@ default long executeLargeUpdate(@Untainted String sql) throws SQLException { * the currently running {@code Statement} * @since 1.8 */ - default long executeLargeUpdate(@Untainted String sql, int autoGeneratedKeys) + default long executeLargeUpdate(@Untainted @SqlEvenQuotes String sql, int autoGeneratedKeys) throws SQLException { throw new SQLFeatureNotSupportedException("executeLargeUpdate not implemented"); } @@ -1326,7 +1327,7 @@ default long executeLargeUpdate(@Untainted String sql, int autoGeneratedKeys) * the currently running {@code Statement} * @since 1.8 */ - default long executeLargeUpdate(@Untainted String sql, int columnIndexes[]) throws SQLException { + default long executeLargeUpdate(@Untainted @SqlEvenQuotes String sql, int columnIndexes[]) throws SQLException { throw new SQLFeatureNotSupportedException("executeLargeUpdate not implemented"); } @@ -1369,7 +1370,7 @@ default long executeLargeUpdate(@Untainted String sql, int columnIndexes[]) thro * the currently running {@code Statement} * @since 1.8 */ - default long executeLargeUpdate(@Untainted String sql, String columnNames[]) + default long executeLargeUpdate(@Untainted @SqlEvenQuotes String sql, String columnNames[]) throws SQLException { throw new SQLFeatureNotSupportedException("executeLargeUpdate not implemented"); } From 194cbc24fce696d546c776cfd583978c6ee765f8 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 11 Mar 2025 11:54:19 -0700 Subject: [PATCH 04/82] There is no need to build the annotated JDK --- README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 22bff8194e9..820e18068d3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Typetools fork of the JDK This fork of the JDK contains type annotations for pluggable type-checking. +It is called "the annotated JDK". It does *not* contain annotations for certain files (because annotations in them cause build failures, especially in the interim builds): @@ -16,7 +17,19 @@ https://github.com/typetools/checker-framework/ . ## Building -See file `azure-pipelines.yml`. Briefly: +You **do not need to build** the annotated JDK in order to use it in the Checker +Framework. + +Put the annotated JDK is in a directory named `jdk/` that is a sibling of your +`checker-framework/` directory. Now, when you build the Checker Framework +(e.g., `cd checker-framework && ./gradlew assemble`), it will automatically +incorporate the annotated JDK into the resulting Checker Framework binaries. +The `jdk/` and `checker-framework/` directories can be clones of the relevant +repositories, or they can be (hard or soft) symbolic links to the clones. + +However, if for some reason you want to build the JDK on its own rather than +just use it from the Checker Framework, see file `azure-pipelines.yml`. +Briefly: ``` bash configure --disable-warnings-as-errors --with-jtreg From aaca02cb7a61f969ee772d45ba2db6509105b656 Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Tue, 11 Mar 2025 22:30:06 -0400 Subject: [PATCH 05/82] Move CI to GitHub Actions (#94) Co-authored-by: Werner Dietl --- .github/workflows/ci.yml | 119 +++++++++++++++++++++++ azure-pipelines.yml | 201 --------------------------------------- 2 files changed, 119 insertions(+), 201 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 azure-pipelines.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000000..c7d88c2845d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,119 @@ +name: CI tests + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ !contains(github.ref, 'heads/master') }} + +jobs: + build_jdk: + name: Build the JDK + runs-on: ubuntu-latest + permissions: + contents: read + env: + JAVA_VERSION: 17 + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: 17 + distribution: 'temurin' + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install --only-upgrade apt + sudo apt-get install gcc-10 g++-10 libcups2-dev libasound2-dev libfontconfig1-dev \ + libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev + - name: Install jtreg + run: | + wget https://builds.shipilev.net/jtreg/jtreg-7.5%2B1.zip -O /tmp/jtreg.zip + unzip /tmp/jtreg.zip -d /tmp/ + - name: Configure the JDK + run: bash ./configure --with-jtreg=/tmp/jtreg --disable-warnings-as-errors + - name: Build the JDK + run: make jdk + + CF: + name: ${{ matrix.script }} on JDK ${{ matrix.java_version }} + runs-on: ubuntu-latest + permissions: + contents: read + strategy: + matrix: + script: ['cftests-junit', 'cftests-nonjunit'] + java_version: [8, 11, 17, 21, 23] + continue-on-error: true + env: + JAVA_VERSION: ${{ matrix.java_version }} + steps: + - uses: actions/checkout@v2 + - name: Set up JDK ${{ matrix.java_version }} + uses: actions/setup-java@v4 + with: + java-version: ${{ matrix.java_version }} + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4.1.0 + + - name: Setup Bazel + uses: bazel-contrib/setup-bazel@0.9.0 + if: ${{ matrix.script == 'cftests-nonjunit' }} + with: + bazelisk-cache: true + disk-cache: ${{ github.workflow }} + repository-cache: true + + - name: Clone plume-scripts + run: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth 1 -q https://github.com/eisop-plume-lib/plume-scripts.git + + - name: Clone git-scripts + run: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth 1 -q https://github.com/eisop-plume-lib/git-scripts.git + + - name: Clone checker-framework + run: /tmp/$USER/git-scripts/git-clone-related eisop checker-framework + + - name: Run test script checker/bin-devel/test-${{ matrix.script }}.sh + run: ./checker/bin-devel/test-${{ matrix.script }}.sh + working-directory: ../checker-framework + + extra: + name: ${{ matrix.script }} on JDK ${{ matrix.java_version }} + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + script: ['plume-lib', 'daikon'] + java_version: [17] + env: + JAVA_VERSION: ${{ matrix.java_version }} + steps: + - uses: actions/checkout@v2 + - name: Set up JDK ${{ matrix.java_version }} + uses: actions/setup-java@v4 + with: + java-version: ${{ matrix.java_version }} + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4.1.0 + + - name: Clone plume-scripts + run: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth 1 -q https://github.com/eisop-plume-lib/plume-scripts.git + + - name: Clone git-scripts + run: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth 1 -q https://github.com/eisop-plume-lib/git-scripts.git + + - name: Clone checker-framework + run: /tmp/$USER/git-scripts/git-clone-related eisop checker-framework + + - name: Run test script checker/bin-devel/test-${{ matrix.script }}.sh + run: ./checker/bin-devel/test-${{ matrix.script }}.sh + working-directory: ../checker-framework diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index b20175a8236..00000000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,201 +0,0 @@ -# variables: -# system.debug: true - -jobs: - -- job: build_jdk - pool: - vmImage: 'ubuntu-latest' - container: wmdietl/cf-ubuntu-jdk17-plus:latest - steps: - - bash: | - whoami - git config --get remote.origin.url - pwd - ls -al - env | sort - displayName: show environment - - bash: pwd && ls && bash ./configure --with-jtreg=/usr/share/jtreg --disable-warnings-as-errors - displayName: configure - - bash: make jdk - timeoutInMinutes: 90 - displayName: make jdk - ## This works only after `make images` - # - bash: build/*/images/jdk/bin/java -version - # displayName: version - ## Don't run tests, which pass only with old version of tools (compilers, etc.). - # - bash: make -C /jdk run-test-tier1 - # displayName: make run-test-tier1 - -# - job: build_jdk17u -# pool: -# vmImage: 'ubuntu-latest' -# container: wmdietl/cf-ubuntu-jdk17-plus:latest -# timeoutInMinutes: 0 -# steps: -# - bash: | -# whoami -# git config --get remote.origin.url -# pwd -# ls -al -# env | sort -# displayName: show environment -# - bash: | -# set -ex -# if [ -d /tmp/$USER/git-scripts ]; \ -# then git -C /tmp/$USER/git-scripts pull -q > /dev/null 2>&1 ; \ -# else mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/eisop-plume-lib/git-scripts.git ; \ -# fi -# displayName: git-scripts -# - bash: | -# set -ex -# if [ -d /tmp/$USER/plume-scripts ]; \ -# then git -C /tmp/$USER/plume-scripts pull -q > /dev/null 2>&1 ; \ -# else mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/eisop-plume-lib/plume-scripts.git ; \ -# fi -# displayName: plume-scripts -# # This creates ../jdk17u . -# # If the depth is too small, the merge will fail. However, we cannot use "--filter=blob:none" -# # because that leads to "fatal: remote error: filter 'combine' not supported". -# - bash: | -# set -ex -# pwd -# ls -al .. || true -# ls -al ../jdk17u || true -# df . -# /tmp/$USER/git-scripts/git-clone-related typetools jdk17u ../jdk17u --depth 999 -# git config --global user.email "you@example.com" -# git config --global user.name "Your Name" -# git config --global core.longpaths true -# git config --global core.protectNTFS false -# cd ../jdk17u && git status -# git diff --exit-code -# echo $? -# displayName: clone-related-jdk17u -# - bash: | -# set -ex -# git config --global user.email "you@example.com" -# git config --global user.name "Your Name" -# git config --global pull.ff true -# git config --global pull.rebase false -# git config --global core.longpaths true -# git config --global core.protectNTFS false -# eval `/tmp/$USER/plume-scripts/ci-info eisop` -# cd ../jdk17u && git status -# echo "About to run: git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH}" -# cd ../jdk17u && git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH} || (git --version && git show && git status && echo "Merge failed; see 'Pull request merge conflicts' at https://github.com/eisop/jdk/blob/master/README.md" && false) -# displayName: git merge -# - bash: cd ../jdk17u && export JT_HOME=/usr/share/jtreg && bash ./configure --with-jtreg=/usr/share/jtreg --disable-warnings-as-errors -# displayName: configure -# - bash: cd ../jdk17u && make jdk -# displayName: make jdk -# ## This works only after `make images` -# # - bash: cd ../jdk17u && build/*/images/jdk/bin/java -version -# # displayName: version -# # - bash: make -C /jdk17u run-test-tier1 -# # timeoutInMinutes: 0 -# # displayName: make run-test-tier1 -# # - bash: make -C /jdk17u :test/jdk:tier1 -# ## Temporarily comment out because of trouble finding junit and jasm -# # - bash: cd ../jdk17u && make run-test TEST="jtreg:test/jdk:tier1" -# # timeoutInMinutes: 0 -# # displayName: make run-test - -- job: test_cftests_all_jdk8 - timeoutInMinutes: 105 - pool: - vmImage: 'ubuntu-latest' - container: wmdietl/cf-ubuntu-jdk8:latest - steps: - - checkout: self - fetchDepth: 25 - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth 1 -q https://github.com/eisop-plume-lib/plume-scripts.git - displayName: clone plume-scripts - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth 1 -q https://github.com/eisop-plume-lib/git-scripts.git - displayName: clone git-scripts - - bash: /tmp/$USER/git-scripts/git-clone-related eisop checker-framework - displayName: clone checker-framework - - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh) - displayName: test-cftests-all.sh - -- job: test_cftests_all_jdk11 - timeoutInMinutes: 120 - pool: - vmImage: 'ubuntu-latest' - container: wmdietl/cf-ubuntu-jdk11:latest - steps: - - checkout: self - fetchDepth: 25 - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/eisop-plume-lib/git-scripts.git - displayName: clone git-scripts - - bash: /tmp/$USER/git-scripts/git-clone-related eisop checker-framework - displayName: clone checker-framework - - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh) - displayName: test-cftests-all.sh -## Here is how to create artifacts that can be downloaded. -# - bash: (cd ../checker-framework/checker/build/jtregJdk11/ && tar -czvf all.tgz all) -# condition: succeededOrFailed() -# displayName: tar jtregJdk11/all -# - publish: $(System.DefaultWorkingDirectory)/../checker-framework/checker/build/jtregJdk11/all.tgz -# artifact: all.tgz -# condition: failed() -# displayName: publish all.tgz - -- job: test_cftests_all_jdk17 - timeoutInMinutes: 120 - pool: - vmImage: 'ubuntu-latest' - container: wmdietl/cf-ubuntu-jdk17:latest - steps: - - checkout: self - fetchDepth: 25 - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/eisop-plume-lib/git-scripts.git - displayName: clone git-scripts - - bash: /tmp/$USER/git-scripts/git-clone-related eisop checker-framework - displayName: clone checker-framework - - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh) - displayName: test-cftests-all.sh - -- job: test_cftests_all_jdk_latest - timeoutInMinutes: 120 - pool: - vmImage: 'ubuntu-latest' - container: wmdietl/cf-ubuntu-jdk-latest:latest - steps: - - checkout: self - fetchDepth: 25 - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/eisop-plume-lib/git-scripts.git - displayName: clone git-scripts - - bash: /tmp/$USER/git-scripts/git-clone-related eisop checker-framework - displayName: clone checker-framework - - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh) - displayName: test-cftests-all.sh - -- job: test_daikon - pool: - vmImage: 'ubuntu-latest' - container: wmdietl/cf-ubuntu-jdk17:latest - timeoutInMinutes: 70 - steps: - - checkout: self - fetchDepth: 25 - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/eisop-plume-lib/git-scripts.git - displayName: clone git-scripts - - bash: /tmp/$USER/git-scripts/git-clone-related eisop checker-framework - displayName: clone checker-framework - - bash: (cd ../checker-framework && checker/bin-devel/test-daikon.sh) - displayName: test-daikon.sh - -- job: test_plume_lib - pool: - vmImage: 'ubuntu-latest' - container: wmdietl/cf-ubuntu-jdk17:latest - steps: - - checkout: self - fetchDepth: 25 - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/eisop-plume-lib/git-scripts.git - displayName: clone git-scripts - - bash: /tmp/$USER/git-scripts/git-clone-related eisop checker-framework - displayName: clone checker-framework - - bash: (cd ../checker-framework && checker/bin-devel/test-plume-lib.sh) - displayName: test-plume-lib.sh From f0fae606600d34c2d98f1e8ad81f64f2590fa9cb Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Wed, 12 Mar 2025 15:35:24 -0400 Subject: [PATCH 06/82] Sync qualifier files from EISOP (#111) --- .../checker/builder/qual/CalledMethods.java | 2 +- ....java => EnsuresCalledMethodsVarargs.java} | 4 +- .../formatter/qual/ConversionCategory.java | 2 +- .../checker/index/qual/IndexFor.java | 2 +- .../checker/mustcall/qual/MustCall.java | 6 +- .../mustcall/qual/MustCallUnknown.java | 6 +- .../nonempty/qual/EnsuresNonEmpty.java | 21 +- .../nonempty/qual/EnsuresNonEmptyIf.java | 57 ++--- .../checker/nonempty/qual/NonEmpty.java | 8 +- .../checker/nonempty/qual/PolyNonEmpty.java | 3 +- .../nonempty/qual/RequiresNonEmpty.java | 39 ++-- .../nonempty/qual/UnknownNonEmpty.java | 8 +- .../checker/optional/qual/EnsuresPresent.java | 4 +- .../checker/optional/qual/OptionalBottom.java | 21 -- .../qual/BinaryNameWithoutPackage.java | 29 --- .../checker/signature/qual/Identifier.java | 6 +- .../checker/sqlquotes/qual/SqlEvenQuotes.java | 28 +++ .../checker/sqlquotes/qual/SqlOddQuotes.java | 30 +++ .../sqlquotes/qual/SqlQuotesBottom.java | 28 +++ .../sqlquotes/qual/SqlQuotesUnknown.java | 26 +++ .../common/aliasing/qual/LeakedToResult.java | 3 +- .../common/aliasing/qual/MaybeAliased.java | 13 +- .../common/aliasing/qual/MaybeLeaked.java | 7 +- .../common/aliasing/qual/NonLeaked.java | 3 +- .../common/aliasing/qual/Unique.java | 3 +- .../qual/EnsuresInitializedFields.java | 65 +++--- .../qual/InitializedFields.java | 17 +- .../qual/InitializedFieldsBottom.java | 9 +- .../qual/PolyInitializedFields.java | 3 +- .../common/reflection/qual/ClassBound.java | 13 +- .../common/reflection/qual/ClassVal.java | 21 +- .../reflection/qual/ClassValBottom.java | 11 +- .../common/reflection/qual/MethodVal.java | 26 ++- .../reflection/qual/MethodValBottom.java | 11 +- .../common/reflection/qual/UnknownClass.java | 13 +- .../common/reflection/qual/UnknownMethod.java | 13 +- .../returnsreceiver/qual/BottomThis.java | 9 +- .../common/returnsreceiver/qual/This.java | 7 +- .../returnsreceiver/qual/UnknownThis.java | 9 +- .../common/subtyping/qual/Bottom.java | 9 +- .../common/subtyping/qual/Unqualified.java | 5 +- .../util/report/qual/ReportUnqualified.java | 7 +- .../common/value/qual/ArrayLen.java | 7 +- .../common/value/qual/ArrayLenRange.java | 27 +-- .../common/value/qual/BoolVal.java | 7 +- .../common/value/qual/BottomVal.java | 35 +-- .../common/value/qual/DoesNotMatchRegex.java | 15 +- .../common/value/qual/DoubleVal.java | 7 +- .../common/value/qual/EnsuresMinLenIf.java | 83 +++---- .../common/value/qual/EnumVal.java | 13 +- .../common/value/qual/IntRange.java | 27 +-- .../qual/IntRangeFromGTENegativeOne.java | 3 +- .../value/qual/IntRangeFromNonNegative.java | 3 +- .../value/qual/IntRangeFromPositive.java | 3 +- .../common/value/qual/IntVal.java | 7 +- .../common/value/qual/MatchesRegex.java | 15 +- .../common/value/qual/MinLen.java | 4 +- .../value/qual/MinLenFieldInvariant.java | 23 +- .../common/value/qual/PolyValue.java | 3 +- .../common/value/qual/StringVal.java | 7 +- .../common/value/qual/UnknownVal.java | 7 +- .../dataflow/qual/AssertMethod.java | 52 ++--- .../checkerframework/dataflow/qual/Pure.java | 14 +- .../framework/qual/AnnotatedFor.java | 20 +- .../framework/qual/CFComment.java | 16 +- .../ConditionalPostconditionAnnotation.java | 12 +- .../framework/qual/Covariant.java | 4 +- .../framework/qual/DefaultFor.java | 115 +++++----- .../framework/qual/DefaultQualifier.java | 96 ++++---- .../qual/DefaultQualifierForUse.java | 4 +- .../framework/qual/EnsuresQualifier.java | 58 ++--- .../framework/qual/EnsuresQualifierIf.java | 76 +++--- .../framework/qual/FieldInvariant.java | 19 +- .../framework/qual/HasQualifierParameter.java | 31 +-- .../framework/qual/LiteralKind.java | 86 +++---- .../framework/qual/MonotonicQualifier.java | 2 +- .../qual/NoDefaultQualifierForUse.java | 4 +- .../framework/qual/NoQualifierParameter.java | 12 +- .../ParametricTypeVariableUseQualifier.java | 40 ++++ .../framework/qual/PolymorphicQualifier.java | 22 +- .../qual/PostconditionAnnotation.java | 12 +- .../qual/PreconditionAnnotation.java | 4 +- .../framework/qual/QualifierArgument.java | 12 +- .../framework/qual/QualifierForLiterals.java | 32 +-- .../framework/qual/RelevantJavaTypes.java | 26 +-- .../framework/qual/RequiresQualifier.java | 54 ++--- .../framework/qual/StubFiles.java | 10 +- .../framework/qual/SubtypeOf.java | 4 +- .../framework/qual/TargetLocations.java | 34 +-- .../framework/qual/TypeKind.java | 84 +++---- .../framework/qual/TypeUseLocation.java | 216 ++++++++++++------ .../framework/qual/Unused.java | 10 +- .../framework/qual/UpperBoundFor.java | 30 +-- 93 files changed, 1181 insertions(+), 933 deletions(-) rename src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/{EnsuresCalledMethodsVarArgs.java => EnsuresCalledMethodsVarargs.java} (91%) delete mode 100644 src/java.base/share/classes/org/checkerframework/checker/optional/qual/OptionalBottom.java delete mode 100644 src/java.base/share/classes/org/checkerframework/checker/signature/qual/BinaryNameWithoutPackage.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java create mode 100644 src/java.base/share/classes/org/checkerframework/framework/qual/ParametricTypeVariableUseQualifier.java diff --git a/src/java.base/share/classes/org/checkerframework/checker/builder/qual/CalledMethods.java b/src/java.base/share/classes/org/checkerframework/checker/builder/qual/CalledMethods.java index 9d27516f9de..1944baff64e 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/builder/qual/CalledMethods.java +++ b/src/java.base/share/classes/org/checkerframework/checker/builder/qual/CalledMethods.java @@ -21,7 +21,7 @@ /** * The names of methods that have definitely been called. * - * @return the names of methods that have definetely been called + * @return the names of methods that have definitely been called */ String[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsVarArgs.java b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsVarargs.java similarity index 91% rename from src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsVarArgs.java rename to src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsVarargs.java index 553ebc5ebd4..ac528e9e733 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsVarArgs.java +++ b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsVarargs.java @@ -10,7 +10,7 @@ *

Consider the following method: * *

- * @EnsuresCalledMethodsVarArgs("m")
+ * @EnsuresCalledMethodsVarargs("m")
  * public void callMOnAll(S s, T t...) { ... }
  * 
* @@ -20,7 +20,7 @@ *

This annotation is not checked. An error will always be issued when it is used. */ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) -public @interface EnsuresCalledMethodsVarArgs { +public @interface EnsuresCalledMethodsVarargs { /** * Returns the methods guaranteed to be invoked on the varargs parameters. diff --git a/src/java.base/share/classes/org/checkerframework/checker/formatter/qual/ConversionCategory.java b/src/java.base/share/classes/org/checkerframework/checker/formatter/qual/ConversionCategory.java index e1cc6f47edb..1aae564c7d9 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/formatter/qual/ConversionCategory.java +++ b/src/java.base/share/classes/org/checkerframework/checker/formatter/qual/ConversionCategory.java @@ -146,7 +146,7 @@ public enum ConversionCategory { typesWithPrimitives.add(unwrapped); } } - this.types = typesWithPrimitives.toArray(new Class[typesWithPrimitives.size()]); + this.types = typesWithPrimitives.toArray(new Class[0]); } } diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/IndexFor.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/IndexFor.java index e08773c837e..3a0a4a7d1ed 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/IndexFor.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/IndexFor.java @@ -19,7 +19,7 @@ * *

{@code
  * class String {
- *   char charAt(@IndexFor("this") index) { ... }
+ *   char charAt(@IndexFor("this") int index) { ... }
  * }
  * }
* diff --git a/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/MustCall.java b/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/MustCall.java index c9357960e9f..c646dfbf5c8 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/MustCall.java +++ b/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/MustCall.java @@ -14,9 +14,9 @@ * An expression of type {@code @MustCall({"m1", "m2"})} may be obligated to call {@code m1()} * and/or {@code m2()} before it is deallocated, but it is not obligated to call any other methods. * - *

This annotation is enforced by the Object Construction Checker's {@code -AcheckMustCall} mode. - * It enforces that the methods {@code m1()} and {@code m2()} are called on the annotated expression - * before it is deallocated. + *

This annotation can be enforced by running the Resource Leak Checker. It enforces that the + * methods {@code m1()} and {@code m2()} are called on the annotated expression before it is + * deallocated. * *

The subtyping relationship is: * diff --git a/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/MustCallUnknown.java b/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/MustCallUnknown.java index 7f234fc1fac..3b42d05c232 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/MustCallUnknown.java +++ b/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/MustCallUnknown.java @@ -12,9 +12,9 @@ * obligation to call any set (even an infinite set!) of methods. This type contains every object. * This type should rarely be written by a programmer. * - *

The Object Construction Checker cannot verify that the property represented by this annotation - * is enforced; that is, the Object Construction Checker will always issue a warning when the value - * of an expression with this type might be de-allocated. + *

The Resource Leak Checker cannot verify that the property represented by this annotation is + * enforced; that is, the Resource Leak Checker will always issue a warning when the value of an + * expression with this type might be de-allocated. * * @checker_framework.manual #must-call-checker Must Call Checker */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmpty.java b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmpty.java index d997df2fc83..125b529e15e 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmpty.java +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmpty.java @@ -1,11 +1,12 @@ package org.checkerframework.checker.nonempty.qual; +import org.checkerframework.framework.qual.InheritedAnnotation; +import org.checkerframework.framework.qual.PostconditionAnnotation; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.InheritedAnnotation; -import org.checkerframework.framework.qual.PostconditionAnnotation; /** * Indicates that a particular expression evaluates to a non-empty value, if the method terminates @@ -42,12 +43,12 @@ @PostconditionAnnotation(qualifier = NonEmpty.class) @InheritedAnnotation public @interface EnsuresNonEmpty { - /** - * The expression (a collection, iterator, iterable, or map) that is non-empty, if the method - * returns normally. - * - * @return the expression (a collection, iterator, iterable, or map) that is non-empty, if the - * method returns normally - */ - String[] value(); + /** + * The expression (a collection, iterator, iterable, or map) that is non-empty, if the method + * returns normally. + * + * @return the expression (a collection, iterator, iterable, or map) that is non-empty, if the + * method returns normally + */ + String[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmptyIf.java b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmptyIf.java index b5af54e90cd..07351e63bdc 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmptyIf.java +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmptyIf.java @@ -1,12 +1,13 @@ package org.checkerframework.checker.nonempty.qual; +import org.checkerframework.framework.qual.ConditionalPostconditionAnnotation; +import org.checkerframework.framework.qual.InheritedAnnotation; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.ConditionalPostconditionAnnotation; -import org.checkerframework.framework.qual.InheritedAnnotation; /** * Indicates that the specific expressions are non-empty, if the method returns the given result @@ -53,35 +54,35 @@ @InheritedAnnotation public @interface EnsuresNonEmptyIf { - /** - * A return value of the method; when the method returns that value, the postcondition holds. - * - * @return the return value of the method for which the postcondition holds - */ - boolean result(); + /** + * A return value of the method; when the method returns that value, the postcondition holds. + * + * @return the return value of the method for which the postcondition holds + */ + boolean result(); - /** - * Returns the Java expressions that are non-empty after the method returns the given result. - * - * @return the Java expressions that are non-empty after the method returns the given result - */ - String[] expression(); + /** + * Returns the Java expressions that are non-empty after the method returns the given result. + * + * @return the Java expressions that are non-empty after the method returns the given result + */ + String[] expression(); - /** - * A wrapper annotation that makes the {@link EnsuresNonEmptyIf} annotation repeatable. - * - *

Programmers generally do not need to write ths. It is created by Java when a programmer - * writes more than one {@link EnsuresNonEmptyIf} annotation at the same location. - */ - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) - @ConditionalPostconditionAnnotation(qualifier = NonEmpty.class) - @interface List { /** - * Returns the repeatable annotations. + * A wrapper annotation that makes the {@link EnsuresNonEmptyIf} annotation repeatable. * - * @return the repeatable annotations + *

Programmers generally do not need to write ths. It is created by Java when a programmer + * writes more than one {@link EnsuresNonEmptyIf} annotation at the same location. */ - EnsuresNonEmptyIf[] value(); - } + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) + @ConditionalPostconditionAnnotation(qualifier = NonEmpty.class) + @interface List { + /** + * Returns the repeatable annotations. + * + * @return the repeatable annotations + */ + EnsuresNonEmptyIf[] value(); + } } diff --git a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/NonEmpty.java b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/NonEmpty.java index d5a7f8c15d5..aca1d5ff95b 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/NonEmpty.java +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/NonEmpty.java @@ -1,15 +1,17 @@ package org.checkerframework.checker.nonempty.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** - * The {@link java.util.Collection Collection}, {@link java.util.Iterator Iterator}, {@link - * java.lang.Iterable Iterable}, or {@link java.util.Map Map} is definitely non-empty. + * The {@link java.util.Collection Collection}, {@link java.util.Iterator Iterator}, {@link Iterable + * Iterable}, or {@link java.util.Map Map}, or {@link java.util.stream.Stream Stream} is definitely + * non-empty. * * @checker_framework.manual #non-empty-checker Non-Empty Checker */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/PolyNonEmpty.java b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/PolyNonEmpty.java index dd538314595..792b8854f80 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/PolyNonEmpty.java +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/PolyNonEmpty.java @@ -1,11 +1,12 @@ package org.checkerframework.checker.nonempty.qual; +import org.checkerframework.framework.qual.PolymorphicQualifier; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.PolymorphicQualifier; /** * A polymorphic qualifier for the Non-Empty type system. diff --git a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/RequiresNonEmpty.java b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/RequiresNonEmpty.java index 45b46d4233d..799a11fa797 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/RequiresNonEmpty.java +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/RequiresNonEmpty.java @@ -1,11 +1,12 @@ package org.checkerframework.checker.nonempty.qual; +import org.checkerframework.framework.qual.PreconditionAnnotation; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.PreconditionAnnotation; /** * Indicates a method precondition: the specified expressions that may be a {@link @@ -71,26 +72,26 @@ @PreconditionAnnotation(qualifier = NonEmpty.class) public @interface RequiresNonEmpty { - /** - * The Java {@link java.util.Collection collection}, {@link java.util.Iterator iterator}, {@link - * java.lang.Iterable iterable}, or {@link java.util.Map map} that must be non-empty. - * - * @return the Java expression that must be non-empty - */ - String[] value(); + /** + * The Java {@link java.util.Collection collection}, {@link java.util.Iterator iterator}, {@link + * java.lang.Iterable iterable}, or {@link java.util.Map map} that must be non-empty. + * + * @return the Java expression that must be non-empty + */ + String[] value(); - /** - * A wrapper annotation that makes the {@link RequiresNonEmpty} annotation repeatable. - * - *

Programmers generally do not need to write this. It is created by Java when a programmer - * writes more than one {@link RequiresNonEmpty} annotation at the same location. - */ - @interface List { /** - * Returns the repeatable annotations. + * A wrapper annotation that makes the {@link RequiresNonEmpty} annotation repeatable. * - * @return the repeatable annotations + *

Programmers generally do not need to write this. It is created by Java when a programmer + * writes more than one {@link RequiresNonEmpty} annotation at the same location. */ - RequiresNonEmpty[] value(); - } + @interface List { + /** + * Returns the repeatable annotations. + * + * @return the repeatable annotations + */ + RequiresNonEmpty[] value(); + } } diff --git a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/UnknownNonEmpty.java b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/UnknownNonEmpty.java index 65900f7fa12..f34be666941 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/UnknownNonEmpty.java +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/UnknownNonEmpty.java @@ -1,16 +1,18 @@ package org.checkerframework.checker.nonempty.qual; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; -import org.checkerframework.framework.qual.SubtypeOf; /** * The {@link java.util.Collection Collection}, {@link java.util.Iterator Iterator}, {@link - * java.lang.Iterable Iterable}, or {@link java.util.Map Map} may or may not be empty. + * java.lang.Iterable Iterable}, {@link java.util.Map Map}, or {@link java.util.stream.Stream + * Stream} may or may not be empty. * * @checker_framework.manual #non-empty-checker Non-Empty Checker */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/optional/qual/EnsuresPresent.java b/src/java.base/share/classes/org/checkerframework/checker/optional/qual/EnsuresPresent.java index a0037970bf8..e96a1552312 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/optional/qual/EnsuresPresent.java +++ b/src/java.base/share/classes/org/checkerframework/checker/optional/qual/EnsuresPresent.java @@ -10,10 +10,10 @@ import java.lang.annotation.Target; /** - * Indicates that the expression evaluates to a non-empty Optional, if the method terminates + * Indicates that the expression evaluates to a present Optional, if the method terminates * successfully. * - *

This postcondition annotation is useful for methods that construct a non-empty Optional: + *

This postcondition annotation is useful for methods that construct a present Optional: * *


  *   {@literal @}EnsuresPresent("optStr")
diff --git a/src/java.base/share/classes/org/checkerframework/checker/optional/qual/OptionalBottom.java b/src/java.base/share/classes/org/checkerframework/checker/optional/qual/OptionalBottom.java
deleted file mode 100644
index 3205701f76b..00000000000
--- a/src/java.base/share/classes/org/checkerframework/checker/optional/qual/OptionalBottom.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.checkerframework.checker.optional.qual;
-
-import org.checkerframework.framework.qual.SubtypeOf;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * The bottom type qualifier for the Optional Checker. The only value of this type is {@code null}.
- * Programmers rarely write this annotation.
- *
- * @checker_framework.manual #optional-checker Optional Checker
- */
-@Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
-@SubtypeOf({Present.class})
-public @interface OptionalBottom {}
diff --git a/src/java.base/share/classes/org/checkerframework/checker/signature/qual/BinaryNameWithoutPackage.java b/src/java.base/share/classes/org/checkerframework/checker/signature/qual/BinaryNameWithoutPackage.java
deleted file mode 100644
index becf579afed..00000000000
--- a/src/java.base/share/classes/org/checkerframework/checker/signature/qual/BinaryNameWithoutPackage.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.checkerframework.checker.signature.qual;
-
-import org.checkerframework.framework.qual.SubtypeOf;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Represents a string that is a {@link BinaryName}, an {@link InternalForm}, and a {@link
- * ClassGetName}. The string represents a class that is in the unnamed package (also known as the
- * default package).
- *
- * 

Examples: - * - *

{@code
- * MyClass
- * MyClass$22
- * }
- * - * @checker_framework.manual #signature-checker Signature Checker - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf({BinaryName.class, InternalForm.class}) -public @interface BinaryNameWithoutPackage {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/signature/qual/Identifier.java b/src/java.base/share/classes/org/checkerframework/checker/signature/qual/Identifier.java index 31126dd0644..8d8a2981318 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/signature/qual/Identifier.java +++ b/src/java.base/share/classes/org/checkerframework/checker/signature/qual/Identifier.java @@ -13,11 +13,7 @@ * * @checker_framework.manual #signature-checker Signature Checker */ -@SubtypeOf({ - DotSeparatedIdentifiers.class, - BinaryNameWithoutPackage.class, - IdentifierOrPrimitiveType.class -}) +@SubtypeOf({DotSeparatedIdentifiers.class, IdentifierOrPrimitiveType.class, InternalForm.class}) @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) diff --git a/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java b/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java new file mode 100644 index 00000000000..af3631f7e3d --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java @@ -0,0 +1,28 @@ +package org.checkerframework.checker.sqlquotes.qual; + +import org.checkerframework.framework.qual.SubtypeOf; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Denotes a String that contains either zero or an even number of unescaped single quotes — + * i.e., there must be either zero or an even number of {@code '} characters in a SqlEvenQuotes + * String that are not preceded immediately by another {@code '} character. (Thus, all SqlEvenQuotes + * Strings ultimately contain an even number of {@code '} characters.) A SqlEvenQuotes String is + * syntactical to be passed to query execution methods and is guaranteed not to affect whether + * subsequent concatenations are interpreted as SQL command code or as SQL query values. + * + *

Common use cases include: SQL query fragments, such as "SELECT * FROM"; properly sanitized + * user input; and complete SQL queries, such as "SELECT * FROM table WHERE field = 'value'". + * + * @checker_framework.manual #sql-quotes-checker SQL Quotes Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQuotesUnknown.class) +public @interface SqlEvenQuotes {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java b/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java new file mode 100644 index 00000000000..63735eec194 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java @@ -0,0 +1,30 @@ +package org.checkerframework.checker.sqlquotes.qual; + +import org.checkerframework.framework.qual.SubtypeOf; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Denotes a String that contains an odd number of unescaped single quotes -- i.e., there must be an + * odd number of ' characters in a SqlOddQuotes String that are not preceded immediately by another + * ' character. (Thus, all SqlOddQuotes Strings ultimately contain an odd number of single quotes, + * escaped or otherwise.) SqlOddQuotes Strings are not syntactical to be passed to query execution + * methods. + * + *

Common use cases include: SQL query fragments to be concatenated with user input, such as + * "SELECT * FROM table WHERE field = '"; SQL query fragments containing user input but missing an + * ending single quote, such as "SELECT * FROM table WHERE field = 'value"; connecting punctuation, + * such as "', "; and any combinations of the above with paired-off single quotes, such as "SELECT * + * FROM table WHERE field1 = 'value1', field2 = 'value2', field3 = '". + * + * @checker_framework.manual #sql-quotes-checker SQL Quotes Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQuotesUnknown.class) +public @interface SqlOddQuotes {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java b/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java new file mode 100644 index 00000000000..7d0f77c14c8 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java @@ -0,0 +1,28 @@ +package org.checkerframework.checker.sqlquotes.qual; + +import org.checkerframework.framework.qual.DefaultFor; +import org.checkerframework.framework.qual.InvisibleQualifier; +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TargetLocations; +import org.checkerframework.framework.qual.TypeUseLocation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Represents the bottom of the SQL Quotes qualifier hierarchy. + * + * @checker_framework.manual #sql-quotes-checker SQL Quotes Checker + * @checker_framework.manual #bottom-type the bottom type + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@InvisibleQualifier +@SubtypeOf({SqlEvenQuotes.class, SqlOddQuotes.class}) +@DefaultFor(value = {TypeUseLocation.LOWER_BOUND}) +public @interface SqlQuotesBottom {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java b/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java new file mode 100644 index 00000000000..f0ea9e0182b --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java @@ -0,0 +1,26 @@ +package org.checkerframework.checker.sqlquotes.qual; + +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.SubtypeOf; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Represents the top of the SQL Quotes qualifier hierarchy. Used to denote a String of which the + * quoting is unknown. Using a SqlQuotesUnknown Strings within a SQL query may be, or lead to, a SQL + * injection vulnerability. + * + *

Common use cases include unsanitized user input. + * + * @checker_framework.manual #sql-quotes-checker SQL Quotes Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({}) +@DefaultQualifierInHierarchy +public @interface SqlQuotesUnknown {} diff --git a/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/LeakedToResult.java b/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/LeakedToResult.java index b93160bde9c..2fa75945acb 100644 --- a/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/LeakedToResult.java +++ b/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/LeakedToResult.java @@ -1,11 +1,12 @@ package org.checkerframework.common.aliasing.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * This annotation is used on a formal parameter to indicate that the parameter may be returned, but diff --git a/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/MaybeAliased.java b/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/MaybeAliased.java index 241fdcbd9d4..409382e15e3 100644 --- a/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/MaybeAliased.java +++ b/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/MaybeAliased.java @@ -1,14 +1,15 @@ package org.checkerframework.common.aliasing.qual; +import org.checkerframework.framework.qual.DefaultFor; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TypeUseLocation; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultFor; -import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; -import org.checkerframework.framework.qual.SubtypeOf; -import org.checkerframework.framework.qual.TypeUseLocation; /** * An expression with this type might have an alias. In other words, some other expression, @@ -23,6 +24,6 @@ @SubtypeOf({}) @DefaultQualifierInHierarchy @DefaultFor( - value = {TypeUseLocation.UPPER_BOUND, TypeUseLocation.LOWER_BOUND}, - types = Void.class) + value = {TypeUseLocation.UPPER_BOUND, TypeUseLocation.LOWER_BOUND}, + types = Void.class) public @interface MaybeAliased {} diff --git a/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/MaybeLeaked.java b/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/MaybeLeaked.java index 9038b6b75b0..0d421fc3242 100644 --- a/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/MaybeLeaked.java +++ b/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/MaybeLeaked.java @@ -1,12 +1,13 @@ package org.checkerframework.common.aliasing.qual; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.InvisibleQualifier; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; -import org.checkerframework.framework.qual.InvisibleQualifier; -import org.checkerframework.framework.qual.SubtypeOf; /** * Temporary type qualifier: diff --git a/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/NonLeaked.java b/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/NonLeaked.java index ad0b07366d5..2417f2e4275 100644 --- a/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/NonLeaked.java +++ b/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/NonLeaked.java @@ -1,11 +1,12 @@ package org.checkerframework.common.aliasing.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * This annotation is used on a formal parameter to indicate that the parameter is not leaked diff --git a/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/Unique.java b/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/Unique.java index 61945114567..af66458ffa7 100644 --- a/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/Unique.java +++ b/src/java.base/share/classes/org/checkerframework/common/aliasing/qual/Unique.java @@ -1,11 +1,12 @@ package org.checkerframework.common.aliasing.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * An expression with this type has no aliases. In other words, no other expression, evaluated at diff --git a/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/EnsuresInitializedFields.java b/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/EnsuresInitializedFields.java index 11e768f2294..264e931be79 100644 --- a/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/EnsuresInitializedFields.java +++ b/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/EnsuresInitializedFields.java @@ -1,14 +1,15 @@ package org.checkerframework.common.initializedfields.qual; +import org.checkerframework.framework.qual.InheritedAnnotation; +import org.checkerframework.framework.qual.PostconditionAnnotation; +import org.checkerframework.framework.qual.QualifierArgument; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.InheritedAnnotation; -import org.checkerframework.framework.qual.PostconditionAnnotation; -import org.checkerframework.framework.qual.QualifierArgument; /** * A method postcondition annotation indicates which fields the method definitely initializes. @@ -22,38 +23,38 @@ @InheritedAnnotation @Repeatable(EnsuresInitializedFields.List.class) public @interface EnsuresInitializedFields { - /** - * The object whose fields this method initializes. - * - * @return object whose fields are initialized - */ - public String[] value() default {"this"}; + /** + * The object whose fields this method initializes. + * + * @return object whose fields are initialized + */ + public String[] value() default {"this"}; - /** - * Fields that this method initializes. - * - * @return fields that this method initializes - */ - @QualifierArgument("value") - public String[] fields(); + /** + * Fields that this method initializes. + * + * @return fields that this method initializes + */ + @QualifierArgument("value") + public String[] fields(); - /** - * A wrapper annotation that makes the {@link EnsuresInitializedFields} annotation repeatable. - * - *

Programmers generally do not need to write this. It is created by Java when a programmer - * writes more than one {@link EnsuresInitializedFields} annotation at the same location. - */ - @Documented - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) - @PostconditionAnnotation(qualifier = InitializedFields.class) - @InheritedAnnotation - public static @interface List { /** - * Return the repeatable annotations. + * A wrapper annotation that makes the {@link EnsuresInitializedFields} annotation repeatable. * - * @return the repeatable annotations + *

Programmers generally do not need to write this. It is created by Java when a programmer + * writes more than one {@link EnsuresInitializedFields} annotation at the same location. */ - EnsuresInitializedFields[] value(); - } + @Documented + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) + @PostconditionAnnotation(qualifier = InitializedFields.class) + @InheritedAnnotation + public static @interface List { + /** + * Return the repeatable annotations. + * + * @return the repeatable annotations + */ + EnsuresInitializedFields[] value(); + } } diff --git a/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/InitializedFields.java b/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/InitializedFields.java index d83042cc0a0..18ea2e2693a 100644 --- a/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/InitializedFields.java +++ b/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/InitializedFields.java @@ -1,11 +1,12 @@ package org.checkerframework.common.initializedfields.qual; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; -import org.checkerframework.framework.qual.SubtypeOf; /** * Indicates which fields have definitely been initialized. @@ -17,10 +18,10 @@ @SubtypeOf({}) @DefaultQualifierInHierarchy public @interface InitializedFields { - /** - * Fields that have been initialized. - * - * @return the initialized fields - */ - public String[] value() default {}; + /** + * Fields that have been initialized. + * + * @return the initialized fields + */ + public String[] value() default {}; } diff --git a/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/InitializedFieldsBottom.java b/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/InitializedFieldsBottom.java index 2f16939d206..628c199eca5 100644 --- a/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/InitializedFieldsBottom.java +++ b/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/InitializedFieldsBottom.java @@ -1,12 +1,13 @@ package org.checkerframework.common.initializedfields.qual; +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TargetLocations; +import org.checkerframework.framework.qual.TypeUseLocation; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; -import org.checkerframework.framework.qual.TargetLocations; -import org.checkerframework.framework.qual.TypeUseLocation; /** * The bottom type qualifier for the Initialized Fields type system. It is the type of {@code null}. @@ -17,5 +18,5 @@ @SubtypeOf({InitializedFields.class}) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) public @interface InitializedFieldsBottom {} diff --git a/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/PolyInitializedFields.java b/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/PolyInitializedFields.java index 1f25542d80a..6fc0b75789e 100644 --- a/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/PolyInitializedFields.java +++ b/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/PolyInitializedFields.java @@ -1,8 +1,9 @@ package org.checkerframework.common.initializedfields.qual; +import org.checkerframework.framework.qual.PolymorphicQualifier; + import java.lang.annotation.ElementType; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.PolymorphicQualifier; /** * Polymorphic qualifier for the Initialized Fields type system. diff --git a/src/java.base/share/classes/org/checkerframework/common/reflection/qual/ClassBound.java b/src/java.base/share/classes/org/checkerframework/common/reflection/qual/ClassBound.java index 0cae3ff79e3..8aa0aee983f 100644 --- a/src/java.base/share/classes/org/checkerframework/common/reflection/qual/ClassBound.java +++ b/src/java.base/share/classes/org/checkerframework/common/reflection/qual/ClassBound.java @@ -1,11 +1,12 @@ package org.checkerframework.common.reflection.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * This represents a {@code Class} object whose run-time value is equal to or a subtype of one of @@ -18,9 +19,9 @@ @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf({UnknownClass.class}) public @interface ClassBound { - /** - * The binary - * name of the class or classes that upper-bound the values of this Class object. - */ - String[] value(); + /** + * The binary + * name of the class or classes that upper-bound the values of this Class object. + */ + String[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/common/reflection/qual/ClassVal.java b/src/java.base/share/classes/org/checkerframework/common/reflection/qual/ClassVal.java index 424efe40bb8..3fb622077f0 100644 --- a/src/java.base/share/classes/org/checkerframework/common/reflection/qual/ClassVal.java +++ b/src/java.base/share/classes/org/checkerframework/common/reflection/qual/ClassVal.java @@ -1,11 +1,12 @@ package org.checkerframework.common.reflection.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * This represents a {@link java.lang.Class Class<T>} object where the set of possible values @@ -19,13 +20,13 @@ @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf({UnknownClass.class}) public @interface ClassVal { - /** - * The name of the type that this Class object represents. The name is a "fully-qualified binary - * name" ({@link org.checkerframework.checker.signature.qual.FqBinaryName}): a primitive or binary name, - * possibly followed by some number of array brackets. - * - * @return the name of the type that this Class object represents - */ - String[] value(); + /** + * The name of the type that this Class object represents. The name is a "fully-qualified binary + * name" ({@link org.checkerframework.checker.signature.qual.FqBinaryName}): a primitive or binary + * name, possibly followed by some number of array brackets. + * + * @return the name of the type that this Class object represents + */ + String[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/common/reflection/qual/ClassValBottom.java b/src/java.base/share/classes/org/checkerframework/common/reflection/qual/ClassValBottom.java index 757845f4e03..e68c8281686 100644 --- a/src/java.base/share/classes/org/checkerframework/common/reflection/qual/ClassValBottom.java +++ b/src/java.base/share/classes/org/checkerframework/common/reflection/qual/ClassValBottom.java @@ -1,14 +1,15 @@ package org.checkerframework.common.reflection.qual; +import org.checkerframework.framework.qual.InvisibleQualifier; +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TargetLocations; +import org.checkerframework.framework.qual.TypeUseLocation; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.InvisibleQualifier; -import org.checkerframework.framework.qual.SubtypeOf; -import org.checkerframework.framework.qual.TargetLocations; -import org.checkerframework.framework.qual.TypeUseLocation; /** * The bottom type in the ClassVal type system. Programmers should rarely write this type. @@ -19,7 +20,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @InvisibleQualifier @SubtypeOf({ClassVal.class, ClassBound.class}) public @interface ClassValBottom {} diff --git a/src/java.base/share/classes/org/checkerframework/common/reflection/qual/MethodVal.java b/src/java.base/share/classes/org/checkerframework/common/reflection/qual/MethodVal.java index 3c7612321b0..1a053e6a1a4 100644 --- a/src/java.base/share/classes/org/checkerframework/common/reflection/qual/MethodVal.java +++ b/src/java.base/share/classes/org/checkerframework/common/reflection/qual/MethodVal.java @@ -1,11 +1,12 @@ package org.checkerframework.common.reflection.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * This represents a set of {@link java.lang.reflect.Method Method} or {@link @@ -23,17 +24,18 @@ @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf({UnknownMethod.class}) public @interface MethodVal { - /** - * The binary - * name of the class that declares this method. - */ - String[] className(); + /** + * The binary + * name of the class that declares this method. + */ + String[] className(); - /** - * The name of the method that this Method object represents. Use {@code } for constructors. - */ - String[] methodName(); + /** + * The name of the method that this Method object represents. Use {@code } for + * constructors. + */ + String[] methodName(); - /** The number of parameters to the method. */ - int[] params(); + /** The number of parameters to the method. */ + int[] params(); } diff --git a/src/java.base/share/classes/org/checkerframework/common/reflection/qual/MethodValBottom.java b/src/java.base/share/classes/org/checkerframework/common/reflection/qual/MethodValBottom.java index c99f8740ccf..3e39e6b04d2 100644 --- a/src/java.base/share/classes/org/checkerframework/common/reflection/qual/MethodValBottom.java +++ b/src/java.base/share/classes/org/checkerframework/common/reflection/qual/MethodValBottom.java @@ -1,14 +1,15 @@ package org.checkerframework.common.reflection.qual; +import org.checkerframework.framework.qual.InvisibleQualifier; +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TargetLocations; +import org.checkerframework.framework.qual.TypeUseLocation; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.InvisibleQualifier; -import org.checkerframework.framework.qual.SubtypeOf; -import org.checkerframework.framework.qual.TargetLocations; -import org.checkerframework.framework.qual.TypeUseLocation; /** * The bottom type in the MethodVal type system. Programmers should rarely write this type. @@ -19,7 +20,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @InvisibleQualifier @SubtypeOf({MethodVal.class}) public @interface MethodValBottom {} diff --git a/src/java.base/share/classes/org/checkerframework/common/reflection/qual/UnknownClass.java b/src/java.base/share/classes/org/checkerframework/common/reflection/qual/UnknownClass.java index f89c5e9f2c5..ccea4c45929 100644 --- a/src/java.base/share/classes/org/checkerframework/common/reflection/qual/UnknownClass.java +++ b/src/java.base/share/classes/org/checkerframework/common/reflection/qual/UnknownClass.java @@ -1,16 +1,17 @@ package org.checkerframework.common.reflection.qual; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; import org.checkerframework.framework.qual.InvisibleQualifier; import org.checkerframework.framework.qual.SubtypeOf; import org.checkerframework.framework.qual.TargetLocations; import org.checkerframework.framework.qual.TypeUseLocation; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + /** * Represents a Class object whose run-time value is not known at compile time. Also represents * non-Class values. @@ -22,7 +23,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.ALL}) @InvisibleQualifier @SubtypeOf({}) @DefaultQualifierInHierarchy diff --git a/src/java.base/share/classes/org/checkerframework/common/reflection/qual/UnknownMethod.java b/src/java.base/share/classes/org/checkerframework/common/reflection/qual/UnknownMethod.java index 34547759c13..bf556909632 100644 --- a/src/java.base/share/classes/org/checkerframework/common/reflection/qual/UnknownMethod.java +++ b/src/java.base/share/classes/org/checkerframework/common/reflection/qual/UnknownMethod.java @@ -1,16 +1,17 @@ package org.checkerframework.common.reflection.qual; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; import org.checkerframework.framework.qual.InvisibleQualifier; import org.checkerframework.framework.qual.SubtypeOf; import org.checkerframework.framework.qual.TargetLocations; import org.checkerframework.framework.qual.TypeUseLocation; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + /** * Represents a {@link java.lang.reflect.Method Method} or {@link java.lang.reflect.Constructor * Constructor} expression whose run-time value is not known at compile time. Also represents @@ -23,7 +24,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.ALL}) @InvisibleQualifier @SubtypeOf({}) @DefaultQualifierInHierarchy diff --git a/src/java.base/share/classes/org/checkerframework/common/returnsreceiver/qual/BottomThis.java b/src/java.base/share/classes/org/checkerframework/common/returnsreceiver/qual/BottomThis.java index 99dd4fcb56b..a3e0f92d8bf 100644 --- a/src/java.base/share/classes/org/checkerframework/common/returnsreceiver/qual/BottomThis.java +++ b/src/java.base/share/classes/org/checkerframework/common/returnsreceiver/qual/BottomThis.java @@ -1,12 +1,13 @@ package org.checkerframework.common.returnsreceiver.qual; +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TargetLocations; +import org.checkerframework.framework.qual.TypeUseLocation; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; -import org.checkerframework.framework.qual.TargetLocations; -import org.checkerframework.framework.qual.TypeUseLocation; /** * The bottom type for the Returns Receiver Checker's type system. Programmers should rarely write @@ -18,5 +19,5 @@ @SubtypeOf({UnknownThis.class}) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) public @interface BottomThis {} diff --git a/src/java.base/share/classes/org/checkerframework/common/returnsreceiver/qual/This.java b/src/java.base/share/classes/org/checkerframework/common/returnsreceiver/qual/This.java index 4d30a59c72a..646aee27a90 100644 --- a/src/java.base/share/classes/org/checkerframework/common/returnsreceiver/qual/This.java +++ b/src/java.base/share/classes/org/checkerframework/common/returnsreceiver/qual/This.java @@ -1,12 +1,13 @@ package org.checkerframework.common.returnsreceiver.qual; +import org.checkerframework.framework.qual.PolymorphicQualifier; +import org.checkerframework.framework.qual.TargetLocations; +import org.checkerframework.framework.qual.TypeUseLocation; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.PolymorphicQualifier; -import org.checkerframework.framework.qual.TargetLocations; -import org.checkerframework.framework.qual.TypeUseLocation; /** * Write {@code @This} on the return type of a method that always returns its receiver ({@code diff --git a/src/java.base/share/classes/org/checkerframework/common/returnsreceiver/qual/UnknownThis.java b/src/java.base/share/classes/org/checkerframework/common/returnsreceiver/qual/UnknownThis.java index 7ada21419f1..eafa025cdfd 100644 --- a/src/java.base/share/classes/org/checkerframework/common/returnsreceiver/qual/UnknownThis.java +++ b/src/java.base/share/classes/org/checkerframework/common/returnsreceiver/qual/UnknownThis.java @@ -1,9 +1,5 @@ package org.checkerframework.common.returnsreceiver.qual; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; import org.checkerframework.framework.qual.DefaultFor; import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; import org.checkerframework.framework.qual.InvisibleQualifier; @@ -12,6 +8,11 @@ import org.checkerframework.framework.qual.SubtypeOf; import org.checkerframework.framework.qual.TypeUseLocation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + /** * The top type for the Returns Receiver Checker's type system. Values of the annotated type might * be the receiver ({@code this}) or might not. Programmers should rarely write this type. diff --git a/src/java.base/share/classes/org/checkerframework/common/subtyping/qual/Bottom.java b/src/java.base/share/classes/org/checkerframework/common/subtyping/qual/Bottom.java index 4e3f318ea79..93c521d8964 100644 --- a/src/java.base/share/classes/org/checkerframework/common/subtyping/qual/Bottom.java +++ b/src/java.base/share/classes/org/checkerframework/common/subtyping/qual/Bottom.java @@ -1,12 +1,13 @@ package org.checkerframework.common.subtyping.qual; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; import org.checkerframework.framework.qual.SubtypeOf; import org.checkerframework.framework.qual.TargetLocations; import org.checkerframework.framework.qual.TypeUseLocation; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + /** * A special annotation intended solely for representing the bottom type in the qualifier hierarchy. * It should not be used! Instead, each type system should define its own dedicated bottom type. @@ -28,5 +29,5 @@ @Documented @SubtypeOf({}) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) public @interface Bottom {} diff --git a/src/java.base/share/classes/org/checkerframework/common/subtyping/qual/Unqualified.java b/src/java.base/share/classes/org/checkerframework/common/subtyping/qual/Unqualified.java index df08edb7b9b..ab339ca71ea 100644 --- a/src/java.base/share/classes/org/checkerframework/common/subtyping/qual/Unqualified.java +++ b/src/java.base/share/classes/org/checkerframework/common/subtyping/qual/Unqualified.java @@ -1,11 +1,12 @@ package org.checkerframework.common.subtyping.qual; +import org.checkerframework.framework.qual.InvisibleQualifier; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.InvisibleQualifier; -import org.checkerframework.framework.qual.SubtypeOf; /** * A special annotation intended solely for representing an unqualified type in the qualifier diff --git a/src/java.base/share/classes/org/checkerframework/common/util/report/qual/ReportUnqualified.java b/src/java.base/share/classes/org/checkerframework/common/util/report/qual/ReportUnqualified.java index d0bd11cf21b..8345f9bfa2c 100644 --- a/src/java.base/share/classes/org/checkerframework/common/util/report/qual/ReportUnqualified.java +++ b/src/java.base/share/classes/org/checkerframework/common/util/report/qual/ReportUnqualified.java @@ -1,13 +1,14 @@ package org.checkerframework.common.util.report.qual; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.InvisibleQualifier; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; -import org.checkerframework.framework.qual.InvisibleQualifier; -import org.checkerframework.framework.qual.SubtypeOf; /** * An annotation intended solely for representing an unqualified type in the qualifier hierarchy for diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/ArrayLen.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/ArrayLen.java index 20b19a15bd6..85c2f5b4d6b 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/ArrayLen.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/ArrayLen.java @@ -1,11 +1,12 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * An annotation indicating the length of an array or a string. If an expression's type has this @@ -23,6 +24,6 @@ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) @SubtypeOf({UnknownVal.class}) public @interface ArrayLen { - /** The possible lengths of the array. */ - int[] value(); + /** The possible lengths of the array. */ + int[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/ArrayLenRange.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/ArrayLenRange.java index 4a1d8baccaa..1dfd0d97e74 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/ArrayLenRange.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/ArrayLenRange.java @@ -1,11 +1,12 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * An expression with this type evaluates to an array or a string whose length is in the given @@ -19,17 +20,17 @@ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) @SubtypeOf(UnknownVal.class) public @interface ArrayLenRange { - /** - * Smallest value in the range, inclusive. - * - * @return the smallest value in the range, inclusive - */ - int from() default 0; + /** + * Smallest value in the range, inclusive. + * + * @return the smallest value in the range, inclusive + */ + int from() default 0; - /** - * Largest value in the range, inclusive. - * - * @return the largest value in the range, inclusive - */ - int to() default Integer.MAX_VALUE; + /** + * Largest value in the range, inclusive. + * + * @return the largest value in the range, inclusive + */ + int to() default Integer.MAX_VALUE; } diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/BoolVal.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/BoolVal.java index 66f5a7fcbeb..adbb4d2d06f 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/BoolVal.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/BoolVal.java @@ -1,11 +1,12 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * An annotation indicating the possible values for a bool type. If an expression's type has this @@ -18,6 +19,6 @@ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) @SubtypeOf({UnknownVal.class}) public @interface BoolVal { - /** The values that the expression might evaluate to. */ - boolean[] value(); + /** The values that the expression might evaluate to. */ + boolean[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/BottomVal.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/BottomVal.java index 8cc40598788..26b00d63827 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/BottomVal.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/BottomVal.java @@ -1,14 +1,15 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.InvisibleQualifier; +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TargetLocations; +import org.checkerframework.framework.qual.TypeUseLocation; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.InvisibleQualifier; -import org.checkerframework.framework.qual.SubtypeOf; -import org.checkerframework.framework.qual.TargetLocations; -import org.checkerframework.framework.qual.TypeUseLocation; /** * The bottom type in the Constant Value type system. Programmers should rarely write this type. @@ -19,20 +20,20 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.UPPER_BOUND, TypeUseLocation.LOWER_BOUND}) @SubtypeOf({ - ArrayLen.class, - BoolVal.class, - DoubleVal.class, - IntVal.class, - StringVal.class, - MatchesRegex.class, - DoesNotMatchRegex.class, - ArrayLenRange.class, - IntRange.class, - IntRangeFromPositive.class, - IntRangeFromGTENegativeOne.class, - IntRangeFromNonNegative.class + ArrayLen.class, + BoolVal.class, + DoubleVal.class, + IntVal.class, + StringVal.class, + MatchesRegex.class, + DoesNotMatchRegex.class, + ArrayLenRange.class, + IntRange.class, + IntRangeFromPositive.class, + IntRangeFromGTENegativeOne.class, + IntRangeFromNonNegative.class }) @InvisibleQualifier public @interface BottomVal {} diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/DoesNotMatchRegex.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/DoesNotMatchRegex.java index 8fde439d8e7..8fb1c2667e1 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/DoesNotMatchRegex.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/DoesNotMatchRegex.java @@ -1,11 +1,12 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * An annotation indicating the possible values for a String type. The annotation's arguments are @@ -23,10 +24,10 @@ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) @SubtypeOf({UnknownVal.class}) public @interface DoesNotMatchRegex { - /** - * A set of Java regular expressions. - * - * @return the regular expressions - */ - String[] value(); + /** + * A set of Java regular expressions. + * + * @return the regular expressions + */ + String[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/DoubleVal.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/DoubleVal.java index 1bfab7a21d7..612ec4da291 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/DoubleVal.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/DoubleVal.java @@ -1,11 +1,12 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * An annotation indicating the possible values for a double or float type. If an expression's type @@ -21,6 +22,6 @@ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) @SubtypeOf({UnknownVal.class}) public @interface DoubleVal { - /** The values that the expression might evaluate to. */ - double[] value(); + /** The values that the expression might evaluate to. */ + double[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/EnsuresMinLenIf.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/EnsuresMinLenIf.java index 89c04613c33..298b1ba3edd 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/EnsuresMinLenIf.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/EnsuresMinLenIf.java @@ -1,14 +1,15 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.ConditionalPostconditionAnnotation; +import org.checkerframework.framework.qual.InheritedAnnotation; +import org.checkerframework.framework.qual.QualifierArgument; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.ConditionalPostconditionAnnotation; -import org.checkerframework.framework.qual.InheritedAnnotation; -import org.checkerframework.framework.qual.QualifierArgument; /** * Indicates that the value of the given expression is a sequence containing at least the given @@ -27,48 +28,48 @@ @InheritedAnnotation @Repeatable(EnsuresMinLenIf.List.class) public @interface EnsuresMinLenIf { - /** - * Returns the return value of the method under which the postcondition to hold. - * - * @return the return value of the method under which the postcondition to hold - */ - boolean result(); + /** + * Returns the return value of the method under which the postcondition holds. + * + * @return the return value of the method under which the postcondition holds + */ + boolean result(); - /** - * Returns Java expression(s) that are a sequence with the given minimum length after the method - * returns {@link #result}. - * - * @return an array of Java expression(s), each of which is a sequence with the given minimum - * length after the method returns {@link #result} - * @checker_framework.manual #java-expressions-as-arguments Syntax of Java expressions - */ - String[] expression(); + /** + * Returns Java expression(s) that are a sequence with the given minimum length after the method + * returns {@link #result}. + * + * @return an array of Java expression(s), each of which is a sequence with the given minimum + * length after the method returns {@link #result} + * @checker_framework.manual #java-expressions-as-arguments Syntax of Java expressions + */ + String[] expression(); - /** - * Returns the minimum number of elements in the sequence. - * - * @return the minimum number of elements in the sequence - */ - @QualifierArgument("value") - int targetValue() default 0; + /** + * Returns the minimum number of elements in the sequence. + * + * @return the minimum number of elements in the sequence + */ + @QualifierArgument("value") + int targetValue() default 0; - /** - * A wrapper annotation that makes the {@link EnsuresMinLenIf} annotation repeatable. - * - *

Programmers generally do not need to write this. It is created by Java when a programmer - * writes more than one {@link EnsuresMinLenIf} annotation at the same location. - */ - @Documented - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) - @ConditionalPostconditionAnnotation(qualifier = MinLen.class) - @InheritedAnnotation - public static @interface List { /** - * Return the repeatable annotations. + * A wrapper annotation that makes the {@link EnsuresMinLenIf} annotation repeatable. * - * @return the repeatable annotations + *

Programmers generally do not need to write this. It is created by Java when a programmer + * writes more than one {@link EnsuresMinLenIf} annotation at the same location. */ - EnsuresMinLenIf[] value(); - } + @Documented + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) + @ConditionalPostconditionAnnotation(qualifier = MinLen.class) + @InheritedAnnotation + public static @interface List { + /** + * Return the repeatable annotations. + * + * @return the repeatable annotations + */ + EnsuresMinLenIf[] value(); + } } diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/EnumVal.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/EnumVal.java index c07b66938ca..cfd60863271 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/EnumVal.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/EnumVal.java @@ -20,10 +20,11 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) public @interface EnumVal { - /** - * The simple names of the possible enum values for an expression with the annotated type. - * - * @return the simple names of the possible enum values for an expression with the annotated type - */ - String[] value(); + /** + * The simple names of the possible enum values for an expression with the annotated type. + * + * @return the simple names of the possible enum values for an expression with the annotated + * type + */ + String[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRange.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRange.java index 74c99b47815..db16428bb02 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRange.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRange.java @@ -1,11 +1,12 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * An expression with this type evaluates to an integral value (byte, short, char, int, or long) in @@ -26,17 +27,17 @@ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) @SubtypeOf(UnknownVal.class) public @interface IntRange { - /** - * Largest value in the range, inclusive. - * - * @return the largest value in the range, inclusive - */ - long from() default Long.MIN_VALUE; + /** + * Smallest value in the range, inclusive. + * + * @return the smallest value in the range, inclusive + */ + long from() default Long.MIN_VALUE; - /** - * Largest value in the range, inclusive. - * - * @return the largest value in the range, inclusive - */ - long to() default Long.MAX_VALUE; + /** + * Largest value in the range, inclusive. + * + * @return the largest value in the range, inclusive + */ + long to() default Long.MAX_VALUE; } diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromGTENegativeOne.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromGTENegativeOne.java index fc65c4a9f20..231f9116087 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromGTENegativeOne.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromGTENegativeOne.java @@ -1,10 +1,11 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * An expression with this type is exactly the same as an {@link IntRange} annotation whose {@code diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromNonNegative.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromNonNegative.java index 434ff259de3..0d39d1bf601 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromNonNegative.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromNonNegative.java @@ -1,10 +1,11 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * An expression with this type is exactly the same as an {@link IntRange} annotation whose {@code diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromPositive.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromPositive.java index 4941505975a..38fc9f88a18 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromPositive.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromPositive.java @@ -1,10 +1,11 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * An expression with this type is exactly the same as an {@link IntRange} annotation whose {@code diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/IntVal.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/IntVal.java index 3ab290f1e7d..6ee20087e74 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/IntVal.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/IntVal.java @@ -1,11 +1,12 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * An annotation indicating the possible values for a byte, short, char, int, or long type. If an @@ -19,6 +20,6 @@ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) @SubtypeOf({UnknownVal.class}) public @interface IntVal { - /** The values that the expression might evaluate to. */ - long[] value(); + /** The values that the expression might evaluate to. */ + long[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/MatchesRegex.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/MatchesRegex.java index 5c10b127c35..49fa1377a88 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/MatchesRegex.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/MatchesRegex.java @@ -1,11 +1,12 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * An annotation indicating the possible values for a String type. The annotation's arguments are @@ -23,10 +24,10 @@ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) @SubtypeOf({UnknownVal.class}) public @interface MatchesRegex { - /** - * A set of Java regular expressions. - * - * @return the regular expressions - */ - String[] value(); + /** + * A set of Java regular expressions. + * + * @return the regular expressions + */ + String[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/MinLen.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/MinLen.java index a05c8431bbf..63a5a04367b 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/MinLen.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/MinLen.java @@ -19,6 +19,6 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) public @interface MinLen { - /** The minimum number of elements in this sequence. */ - int value() default 0; + /** The minimum number of elements in this sequence. */ + int value() default 0; } diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/MinLenFieldInvariant.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/MinLenFieldInvariant.java index bf120018cd3..ffe7d404fd0 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/MinLenFieldInvariant.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/MinLenFieldInvariant.java @@ -1,12 +1,13 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.FieldInvariant; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.FieldInvariant; /** * A specialization of {@link FieldInvariant} for specifying the minimum length of an array. A class @@ -20,15 +21,15 @@ @Inherited public @interface MinLenFieldInvariant { - /** - * Min length of the array. Must be greater than the min length of the array as declared in the - * superclass. - */ - int[] minLen(); + /** + * Min length of the array. Must be greater than the min length of the array as declared in the + * superclass. + */ + int[] minLen(); - /** - * The field that has an array length qualifier in the class on which the field invariant is - * written. The field must be final and declared in a superclass. - */ - String[] field(); + /** + * The field that has an array length qualifier in the class on which the field invariant is + * written. The field must be final and declared in a superclass. + */ + String[] field(); } diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/PolyValue.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/PolyValue.java index 8ae998b9b7f..99e6ddec353 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/PolyValue.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/PolyValue.java @@ -1,11 +1,12 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.PolymorphicQualifier; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.PolymorphicQualifier; /** * A polymorphic qualifier for the Constant Value Checker. diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/StringVal.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/StringVal.java index 6f0ccb4dd77..95472e9746f 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/StringVal.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/StringVal.java @@ -1,11 +1,12 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * An annotation indicating the possible values for a String type. If an expression's type has this @@ -18,6 +19,6 @@ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) @SubtypeOf({UnknownVal.class}) public @interface StringVal { - /** The values that the expression might evaluate to. */ - String[] value(); + /** The values that the expression might evaluate to. */ + String[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/UnknownVal.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/UnknownVal.java index 1ae28c0f75b..fdbd1ff373c 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/UnknownVal.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/UnknownVal.java @@ -1,13 +1,14 @@ package org.checkerframework.common.value.qual; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.InvisibleQualifier; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; -import org.checkerframework.framework.qual.InvisibleQualifier; -import org.checkerframework.framework.qual.SubtypeOf; /** * UnknownVal is a type annotation indicating that the expression's value is not known at compile diff --git a/src/java.base/share/classes/org/checkerframework/dataflow/qual/AssertMethod.java b/src/java.base/share/classes/org/checkerframework/dataflow/qual/AssertMethod.java index 4dd0ee58614..5622d6de0f2 100644 --- a/src/java.base/share/classes/org/checkerframework/dataflow/qual/AssertMethod.java +++ b/src/java.base/share/classes/org/checkerframework/dataflow/qual/AssertMethod.java @@ -38,32 +38,32 @@ @Target(ElementType.METHOD) public @interface AssertMethod { - /** - * The class of the exception thrown by this method. The default is {@link AssertionError}. - * - * @return class of the exception thrown by this method - */ - Class value() default AssertionError.class; + /** + * The class of the exception thrown by this method. The default is {@link AssertionError}. + * + * @return class of the exception thrown by this method + */ + Class value() default AssertionError.class; - /** - * The one-based index of the boolean parameter that is tested. - * - * @return the one-based index of the boolean parameter that is tested - */ - int parameter() default 1; + /** + * The one-based index of the boolean parameter that is tested. + * + * @return the one-based index of the boolean parameter that is tested + */ + int parameter() default 1; - /** - * Returns whether this method asserts that the boolean expression is false. - * - *

For example, Junit's Assertions.assertFalse(...) - * throws an exception if the first argument is false. So it is annotated as follows: - * - *

@AssertMethod(value = AssertionFailedError.class, isAssertFalse = true)
-   * public static void assertFalse(boolean condition);
-   * 
- * - * @return the value for {@link #parameter} on which the method throws an exception - */ - boolean isAssertFalse() default false; + /** + * Returns whether this method asserts that the boolean expression is false. + * + *

For example, JUnit's Assertions.assertFalse(...) + * throws an exception if the first argument is false. So it is annotated as follows: + * + *

@AssertMethod(value = AssertionFailedError.class, isAssertFalse = true)
+     * public static void assertFalse(boolean condition);
+     * 
+ * + * @return the value for {@link #parameter} on which the method throws an exception + */ + boolean isAssertFalse() default false; } diff --git a/src/java.base/share/classes/org/checkerframework/dataflow/qual/Pure.java b/src/java.base/share/classes/org/checkerframework/dataflow/qual/Pure.java index 82cdb596879..1b57e655fd9 100644 --- a/src/java.base/share/classes/org/checkerframework/dataflow/qual/Pure.java +++ b/src/java.base/share/classes/org/checkerframework/dataflow/qual/Pure.java @@ -26,12 +26,12 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) public @interface Pure { - /** The type of purity. */ - public static enum Kind { - /** The method has no visible side effects. */ - SIDE_EFFECT_FREE, + /** The type of purity. */ + enum Kind { + /** The method has no visible side effects. */ + SIDE_EFFECT_FREE, - /** The method returns exactly the same value when called in the same environment. */ - DETERMINISTIC - } + /** The method returns exactly the same value when called in the same environment. */ + DETERMINISTIC + } } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/AnnotatedFor.java b/src/java.base/share/classes/org/checkerframework/framework/qual/AnnotatedFor.java index 8c2844ee992..48c4f7ab47f 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/AnnotatedFor.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/AnnotatedFor.java @@ -29,14 +29,14 @@ @Retention(RetentionPolicy.SOURCE) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PACKAGE}) public @interface AnnotatedFor { - /** - * Returns the type systems for which the class has been annotated. Legal arguments are any string - * that may be passed to the {@code -processor} command-line argument: the fully-qualified class - * name for the checker, or a shorthand for built-in checkers. Using the annotation with no - * arguments, as in {@code @AnnotatedFor({})}, has no effect. - * - * @return the type systems for which the class has been annotated - * @checker_framework.manual #shorthand-for-checkers Short names for built-in checkers - */ - String[] value(); + /** + * Returns the type systems for which the class has been annotated. Legal arguments are any + * string that may be passed to the {@code -processor} command-line argument: the + * fully-qualified class name for the checker, or a shorthand for built-in checkers. Using the + * annotation with no arguments, as in {@code @AnnotatedFor({})}, has no effect. + * + * @return the type systems for which the class has been annotated + * @checker_framework.manual #shorthand-for-checkers Short names for built-in checkers + */ + String[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/CFComment.java b/src/java.base/share/classes/org/checkerframework/framework/qual/CFComment.java index f9ef370b591..c6ed6140cf9 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/CFComment.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/CFComment.java @@ -30,12 +30,12 @@ @Documented @Retention(RetentionPolicy.SOURCE) public @interface CFComment { - /** - * Comments about Checker Framework annotations. The text is not interpreted by the Checker - * Framework. - * - *

If you prefix each comment by the name of the type system, the comments are easier to - * understand and search for. - */ - String[] value(); + /** + * Comments about Checker Framework annotations. The text is not interpreted by the Checker + * Framework. + * + *

If you prefix each comment by the name of the type system, the comments are easier to + * understand and search for. + */ + String[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/ConditionalPostconditionAnnotation.java b/src/java.base/share/classes/org/checkerframework/framework/qual/ConditionalPostconditionAnnotation.java index 9b7feb69237..ac65025991e 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/ConditionalPostconditionAnnotation.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/ConditionalPostconditionAnnotation.java @@ -65,10 +65,10 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.ANNOTATION_TYPE}) public @interface ConditionalPostconditionAnnotation { - /** - * The qualifier that will be established as a postcondition. - * - *

This element is analogous to {@link EnsuresQualifierIf#qualifier()}. - */ - Class qualifier(); + /** + * The qualifier that will be established as a postcondition. + * + *

This element is analogous to {@link EnsuresQualifierIf#qualifier()}. + */ + Class qualifier(); } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/Covariant.java b/src/java.base/share/classes/org/checkerframework/framework/qual/Covariant.java index 1599464f6ac..ac79c2e99db 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/Covariant.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/Covariant.java @@ -32,6 +32,6 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) public @interface Covariant { - /** The zero-based indices of the type parameters that should be treated covariantly. */ - int[] value(); + /** The zero-based indices of the type parameters that should be treated covariantly. */ + int[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultFor.java b/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultFor.java index f1c0fde504d..2b75ecf37a9 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultFor.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultFor.java @@ -16,6 +16,13 @@ *

  • all uses of a particular kind of type. * * + * An example is the declaration + * + *
    
    + * {@literal @}DefaultFor(TypeUseLocation.LOWER_BOUND)
    + * {@literal @}interface MyAnno {}
    + * 
    + * *

    The default applies to every match for any of this annotation's conditions. * * @see TypeUseLocation @@ -26,62 +33,62 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface DefaultFor { - /** - * Returns the locations to which the annotation should be applied. - * - * @return the locations to which the annotation should be applied - */ - TypeUseLocation[] value() default {}; + /** + * Returns the locations to which the annotation should be applied. + * + * @return the locations to which the annotation should be applied + */ + TypeUseLocation[] value() default {}; - /** - * Returns {@link TypeKind}s of types for which an annotation should be implicitly added. - * - * @return {@link TypeKind}s of types for which an annotation should be implicitly added - */ - TypeKind[] typeKinds() default {}; + /** + * Returns {@link TypeKind}s of types for which an annotation should be implicitly added. + * + * @return {@link TypeKind}s of types for which an annotation should be implicitly added + */ + TypeKind[] typeKinds() default {}; - /** - * Returns {@link Class}es for which an annotation should be applied. For example, if - * {@code @MyAnno} is meta-annotated with {@code @DefaultFor(classes=String.class)}, then every - * occurrence of {@code String} is actually {@code @MyAnno String}. - * - *

    Only the given types, not their subtypes, receive the default. For instance, if the {@code - * types} element contains only {@code Iterable}, then the default does not apply to a variable or - * expression of type {@code Collection} which is a subtype of {@code Iterable}. - * - * @return {@link Class}es for which an annotation should be applied - */ - Class[] types() default {}; + /** + * Returns {@link Class}es for which an annotation should be applied. For example, if + * {@code @MyAnno} is meta-annotated with {@code @DefaultFor(classes=String.class)}, then every + * occurrence of {@code String} is actually {@code @MyAnno String}. + * + *

    Only the given types, not their subtypes, receive the default. For instance, if the {@code + * types} element contains only {@code Iterable}, then the default does not apply to a variable + * or expression of type {@code Collection} which is a subtype of {@code Iterable}. + * + * @return {@link Class}es for which an annotation should be applied + */ + Class[] types() default {}; - /** - * Returns regular expressions matching names of variables, to whose types the annotation should - * be applied as a default. If a regular expression matches the name of a method, the annotation - * is applied as a default to the return type. - * - *

    The regular expression must match the entire variable or method name. For example, to match - * any name that contains "foo", use ".*foo.*". - * - *

    The default does not apply if the name matches any of the regexes in {@link - * #namesExceptions}. - * - *

    This affects formal parameter types only if one of the following is true: - * - *

      - *
    • The method's source code is available; that is, the method is type-checked along with - * client calls. - *
    • When the method was compiled in a previous run of javac, either the processor was run or - * the {@code -g} command-line option was provided. - *
    - * - * @return regular expressions matching variables to whose type an annotation should be applied - */ - String[] names() default {}; + /** + * Returns regular expressions matching names of variables, to whose types the annotation should + * be applied as a default. If a regular expression matches the name of a method, the annotation + * is applied as a default to the return type. + * + *

    The regular expression must match the entire variable or method name. For example, to + * match any name that contains "foo", use ".*foo.*". + * + *

    The default does not apply if the name matches any of the regexes in {@link + * #namesExceptions}. + * + *

    This affects formal parameter types only if one of the following is true: + * + *

      + *
    • The method's source code is available; that is, the method is type-checked along with + * client calls. + *
    • When the method was compiled in a previous run of javac, either the processor was run + * or the {@code -g} command-line option was provided. + *
    + * + * @return regular expressions matching variables to whose type an annotation should be applied + */ + String[] names() default {}; - /** - * Returns exceptions to regular expression rules. - * - * @return exceptions to regular expression rules - * @see #names - */ - String[] namesExceptions() default {}; + /** + * Returns exceptions to regular expression rules. + * + * @return exceptions to regular expression rules + * @see #names + */ + String[] namesExceptions() default {}; } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultQualifier.java b/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultQualifier.java index 7409d914144..936cd8644ce 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultQualifier.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultQualifier.java @@ -26,6 +26,9 @@ *   class MyClass { ... } *
  • * + *

    Defaults on a package also apply to subpackages, unless the {@code applyToSubpackages} field + * is set to false. + * *

    This annotation currently has no effect in stub files. * * @see org.checkerframework.framework.qual.TypeUseLocation @@ -34,44 +37,8 @@ * @checker_framework.manual #defaults Default qualifier for unannotated types */ @Documented -@Retention(RetentionPolicy.SOURCE) +@Retention(RetentionPolicy.RUNTIME) @Target({ - ElementType.PACKAGE, - ElementType.TYPE, - ElementType.CONSTRUCTOR, - ElementType.METHOD, - ElementType.FIELD, - ElementType.LOCAL_VARIABLE, - ElementType.PARAMETER -}) -@Repeatable(DefaultQualifier.List.class) -public @interface DefaultQualifier { - - /** - * The Class for the default annotation. - * - *

    To prevent affecting other type systems, always specify an annotation in your own type - * hierarchy. (For example, do not set {@link - * org.checkerframework.common.subtyping.qual.Unqualified} as the default.) - */ - Class value(); - - /** - * Returns the locations to which the annotation should be applied. - * - * @return the locations to which the annotation should be applied - */ - TypeUseLocation[] locations() default {TypeUseLocation.ALL}; - - /** - * A wrapper annotation that makes the {@link DefaultQualifier} annotation repeatable. - * - *

    Programmers generally do not need to write this. It is created by Java when a programmer - * writes more than one {@link DefaultQualifier} annotation at the same location. - */ - @Documented - @Retention(RetentionPolicy.RUNTIME) - @Target({ ElementType.PACKAGE, ElementType.TYPE, ElementType.CONSTRUCTOR, @@ -79,13 +46,56 @@ ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.PARAMETER - }) - public static @interface List { +}) +@Repeatable(DefaultQualifier.List.class) +public @interface DefaultQualifier { + + /** + * The Class for the default annotation. + * + *

    To prevent affecting other type systems, always specify an annotation in your own type + * hierarchy. (For example, do not set {@link + * org.checkerframework.common.subtyping.qual.Unqualified} as the default.) + */ + Class value(); + + /** + * Returns the locations to which the annotation should be applied. + * + * @return the locations to which the annotation should be applied + */ + TypeUseLocation[] locations() default {TypeUseLocation.ALL}; + + /** + * When used on a package, whether the defaults should also apply to subpackages. + * + * @return whether the default should be inherited by subpackages + */ + boolean applyToSubpackages() default true; + /** - * Return the repeatable annotations. + * A wrapper annotation that makes the {@link DefaultQualifier} annotation repeatable. * - * @return the repeatable annotations + *

    Programmers generally do not need to write this. It is created by Java when a programmer + * writes more than one {@link DefaultQualifier} annotation at the same location. */ - DefaultQualifier[] value(); - } + @Documented + @Retention(RetentionPolicy.RUNTIME) + @Target({ + ElementType.PACKAGE, + ElementType.TYPE, + ElementType.CONSTRUCTOR, + ElementType.METHOD, + ElementType.FIELD, + ElementType.LOCAL_VARIABLE, + ElementType.PARAMETER + }) + public static @interface List { + /** + * Return the repeatable annotations. + * + * @return the repeatable annotations + */ + DefaultQualifier[] value(); + } } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultQualifierForUse.java b/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultQualifierForUse.java index c88065e8d1a..961ed0421f9 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultQualifierForUse.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultQualifierForUse.java @@ -15,6 +15,6 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface DefaultQualifierForUse { - /** Qualifier to add to all unannotated uses of the type with this declaration annotation. */ - Class[] value() default {}; + /** Qualifier to add to all unannotated uses of the type with this declaration annotation. */ + Class[] value() default {}; } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifier.java b/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifier.java index 3c897376109..f6d4232f977 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifier.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifier.java @@ -36,37 +36,39 @@ @InheritedAnnotation @Repeatable(EnsuresQualifier.List.class) public @interface EnsuresQualifier { - /** - * Returns the Java expressions for which the qualifier holds after successful method termination. - * - * @return the Java expressions for which the qualifier holds after successful method termination - * @checker_framework.manual #java-expressions-as-arguments Syntax of Java expressions - */ - String[] expression(); + /** + * Returns the Java expressions for which the qualifier holds after successful method + * termination. + * + * @return the Java expressions for which the qualifier holds after successful method + * termination + * @checker_framework.manual #java-expressions-as-arguments Syntax of Java expressions + */ + String[] expression(); - /** - * Returns the qualifier that is guaranteed to hold on successful termination of the method. - * - * @return the qualifier that is guaranteed to hold on successful termination of the method - */ - Class qualifier(); + /** + * Returns the qualifier that is guaranteed to hold on successful termination of the method. + * + * @return the qualifier that is guaranteed to hold on successful termination of the method + */ + Class qualifier(); - /** - * A wrapper annotation that makes the {@link EnsuresQualifier} annotation repeatable. - * - *

    Programmers generally do not need to write this. It is created by Java when a programmer - * writes more than one {@link EnsuresQualifier} annotation at the same location. - */ - @Documented - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) - @InheritedAnnotation - public static @interface List { /** - * Return the repeatable annotations. + * A wrapper annotation that makes the {@link EnsuresQualifier} annotation repeatable. * - * @return the repeatable annotations + *

    Programmers generally do not need to write this. It is created by Java when a programmer + * writes more than one {@link EnsuresQualifier} annotation at the same location. */ - EnsuresQualifier[] value(); - } + @Documented + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) + @InheritedAnnotation + public static @interface List { + /** + * Return the repeatable annotations. + * + * @return the repeatable annotations + */ + EnsuresQualifier[] value(); + } } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifierIf.java b/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifierIf.java index e5e6734255d..4d502b6d38d 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifierIf.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifierIf.java @@ -39,48 +39,48 @@ @InheritedAnnotation @Repeatable(EnsuresQualifierIf.List.class) public @interface EnsuresQualifierIf { - /** - * Returns the return value of the method that needs to hold for the postcondition to hold. - * - * @return the return value of the method that needs to hold for the postcondition to hold - */ - boolean result(); + /** + * Returns the return value of the method that needs to hold for the postcondition to hold. + * + * @return the return value of the method that needs to hold for the postcondition to hold + */ + boolean result(); - /** - * Returns the Java expressions for which the qualifier holds if the method terminates with return - * value {@link #result()}. - * - * @return the Java expressions for which the qualifier holds if the method terminates with return - * value {@link #result()} - * @checker_framework.manual #java-expressions-as-arguments Syntax of Java expressions - */ - String[] expression(); + /** + * Returns the Java expressions for which the qualifier holds if the method terminates with + * return value {@link #result()}. + * + * @return the Java expressions for which the qualifier holds if the method terminates with + * return value {@link #result()} + * @checker_framework.manual #java-expressions-as-arguments Syntax of Java expressions + */ + String[] expression(); - /** - * Returns the qualifier that is guaranteed to hold if the method terminates with return value - * {@link #result()}. - * - * @return the qualifier that is guaranteed to hold if the method terminates with return value - * {@link #result()} - */ - Class qualifier(); + /** + * Returns the qualifier that is guaranteed to hold if the method terminates with return value + * {@link #result()}. + * + * @return the qualifier that is guaranteed to hold if the method terminates with return value + * {@link #result()} + */ + Class qualifier(); - /** - * A wrapper annotation that makes the {@link EnsuresQualifierIf} annotation repeatable. - * - *

    Programmers generally do not need to write this. It is created by Java when a programmer - * writes more than one {@link EnsuresQualifierIf} annotation at the same location. - */ - @Documented - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD}) - @InheritedAnnotation - public static @interface List { /** - * Return the repeatable annotations. + * A wrapper annotation that makes the {@link EnsuresQualifierIf} annotation repeatable. * - * @return the repeatable annotations + *

    Programmers generally do not need to write this. It is created by Java when a programmer + * writes more than one {@link EnsuresQualifierIf} annotation at the same location. */ - EnsuresQualifierIf[] value(); - } + @Documented + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD}) + @InheritedAnnotation + public static @interface List { + /** + * Return the repeatable annotations. + * + * @return the repeatable annotations + */ + EnsuresQualifierIf[] value(); + } } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/FieldInvariant.java b/src/java.base/share/classes/org/checkerframework/framework/qual/FieldInvariant.java index 037312637f6..2f5d65e8cf5 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/FieldInvariant.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/FieldInvariant.java @@ -27,14 +27,15 @@ @Inherited public @interface FieldInvariant { - /** - * The qualifier on the field. Must be a subtype of the qualifier on the declaration of the field. - */ - Class[] qualifier(); + /** + * The qualifier on the field. Must be a subtype of the qualifier on the declaration of the + * field. + */ + Class[] qualifier(); - /** - * The field that has a more precise type, in the class on which the {@code FieldInvariant} - * annotation is written. The field must be declared in a superclass and must be {@code final}. - */ - String[] field(); + /** + * The field that has a more precise type, in the class on which the {@code FieldInvariant} + * annotation is written. The field must be declared in a superclass and must be {@code final}. + */ + String[] field(); } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/HasQualifierParameter.java b/src/java.base/share/classes/org/checkerframework/framework/qual/HasQualifierParameter.java index 9cc75018286..cd59052d2f5 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/HasQualifierParameter.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/HasQualifierParameter.java @@ -9,13 +9,15 @@ import java.lang.annotation.Target; /** - * This is a declaration annotation that applies to type declarations and packages. On a type, it - * means that the class conceptually takes a type qualifier parameter, though there is nowhere to - * write it because the class hard-codes a Java basetype rather than taking a type parameter. - * Writing {@code HasQualifierParameter} on a package is the same as writing it on each class in - * that package. + * This is a declaration annotation that applies to type declarations and packages. On a + * type, it means that the class conceptually takes a type qualifier parameter, though there + * is nowhere to write it because the class hard-codes a Java basetype rather than taking a type + * parameter. Writing {@code HasQualifierParameter} on a package is the same as writing it on + * each class in that package. * - *

    Writing {@code @HasQualifierParameter} on a type declaration has two effects. + *

    Written on a type declaration

    + * + *

    Writing {@code @HasQualifierParameter} on a type declaration has two effects. * *

      *
    1. Invariant subtyping is used for occurrences of the type: no two occurrences of the type @@ -55,7 +57,10 @@ * {@code @Untainted} MyStringBuffer * * - *

      When a class is {@code @HasQualifierParameter}, all its subclasses are as well. + *

      When a type is {@code @HasQualifierParameter}, all its subtypes are as well. That is, the + * {@code @HasQualifierParameter} annotation is inherited by subtypes. + * + *

      Written on a package

      * *

      When {@code @HasQualifierParameter} is written on a package, it is equivalent to writing that * annotation on each class in the package or in a sub-package. It can be disabled on a specific @@ -70,10 +75,10 @@ @Target({ElementType.TYPE, ElementType.PACKAGE}) public @interface HasQualifierParameter { - /** - * Class of the top qualifier for the hierarchy for which this class has a qualifier parameter. - * - * @return the value - */ - Class[] value(); + /** + * Class of the top qualifier for the hierarchy for which this class has a qualifier parameter. + * + * @return the value + */ + Class[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/LiteralKind.java b/src/java.base/share/classes/org/checkerframework/framework/qual/LiteralKind.java index 7b3b291007b..e027ae6153f 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/LiteralKind.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/LiteralKind.java @@ -13,48 +13,50 @@ */ // https://docs.oracle.com/javase/8/docs/technotes/tools/findingclasses.html#bootclass public enum LiteralKind { - /** Corresponds to {@link com.sun.source.tree.Tree.Kind#NULL_LITERAL} trees. */ - NULL, - /** Corresponds to {@link com.sun.source.tree.Tree.Kind#INT_LITERAL} trees. */ - INT, - /** Corresponds to {@link com.sun.source.tree.Tree.Kind#LONG_LITERAL} trees. */ - LONG, - /** Corresponds to {@link com.sun.source.tree.Tree.Kind#FLOAT_LITERAL} trees. */ - FLOAT, - /** Corresponds to {@link com.sun.source.tree.Tree.Kind#DOUBLE_LITERAL} trees. */ - DOUBLE, - /** Corresponds to {@link com.sun.source.tree.Tree.Kind#BOOLEAN_LITERAL} trees. */ - BOOLEAN, - /** Corresponds to {@link com.sun.source.tree.Tree.Kind#CHAR_LITERAL} trees. */ - CHAR, - /** Corresponds to {@link com.sun.source.tree.Tree.Kind#STRING_LITERAL} trees. */ - STRING, - /** Shorthand for all other LiteralKind constants, other than PRIMITIVE. */ - ALL, - /** Shorthand for all primitive LiteralKind constants: INT, LONG, FLOAT, DOUBLE, BOOLEAN, CHAR. */ - PRIMITIVE; + /** Corresponds to {@link com.sun.source.tree.Tree.Kind#NULL_LITERAL} trees. */ + NULL, + /** Corresponds to {@link com.sun.source.tree.Tree.Kind#INT_LITERAL} trees. */ + INT, + /** Corresponds to {@link com.sun.source.tree.Tree.Kind#LONG_LITERAL} trees. */ + LONG, + /** Corresponds to {@link com.sun.source.tree.Tree.Kind#FLOAT_LITERAL} trees. */ + FLOAT, + /** Corresponds to {@link com.sun.source.tree.Tree.Kind#DOUBLE_LITERAL} trees. */ + DOUBLE, + /** Corresponds to {@link com.sun.source.tree.Tree.Kind#BOOLEAN_LITERAL} trees. */ + BOOLEAN, + /** Corresponds to {@link com.sun.source.tree.Tree.Kind#CHAR_LITERAL} trees. */ + CHAR, + /** Corresponds to {@link com.sun.source.tree.Tree.Kind#STRING_LITERAL} trees. */ + STRING, + /** Shorthand for all other LiteralKind constants, other than PRIMITIVE. */ + ALL, + /** + * Shorthand for all primitive LiteralKind constants: INT, LONG, FLOAT, DOUBLE, BOOLEAN, CHAR. + */ + PRIMITIVE; - /** - * Returns all LiteralKinds except for ALL and PRIMITIVE (which are shorthands for groups of other - * LiteralKinds). - * - * @return list of LiteralKinds except for ALL and PRIMITIVE - */ - public static List allLiteralKinds() { - List list = new ArrayList<>(Arrays.asList(values())); - list.remove(ALL); - list.remove(PRIMITIVE); - return list; - } + /** + * Returns all LiteralKinds except for ALL and PRIMITIVE (which are shorthands for groups of + * other LiteralKinds). + * + * @return list of LiteralKinds except for ALL and PRIMITIVE + */ + public static List allLiteralKinds() { + List list = new ArrayList<>(Arrays.asList(values())); + list.remove(ALL); + list.remove(PRIMITIVE); + return list; + } - /** - * Returns the primitive {@code LiteralKind}s: INT, LONG, FLOAT, DOUBLE, BOOLEAN, CHAR. This is - * all LiteralKinds except for NULL, STRING, and ones that are shorthands for groups of other - * LiteralKinds. - * - * @return list of LiteralKinds except for NULL and STRING - */ - public static List primitiveLiteralKinds() { - return Arrays.asList(INT, LONG, FLOAT, DOUBLE, BOOLEAN, CHAR); - } + /** + * Returns the primitive {@code LiteralKind}s: INT, LONG, FLOAT, DOUBLE, BOOLEAN, CHAR. This is + * all LiteralKinds except for NULL, STRING, and ones that are shorthands for groups of other + * LiteralKinds. + * + * @return list of LiteralKinds except for NULL and STRING + */ + public static List primitiveLiteralKinds() { + return Arrays.asList(INT, LONG, FLOAT, DOUBLE, BOOLEAN, CHAR); + } } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/MonotonicQualifier.java b/src/java.base/share/classes/org/checkerframework/framework/qual/MonotonicQualifier.java index 73b2fde809a..25232ebf100 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/MonotonicQualifier.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/MonotonicQualifier.java @@ -39,5 +39,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.ANNOTATION_TYPE}) public @interface MonotonicQualifier { - Class value(); + Class value(); } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/NoDefaultQualifierForUse.java b/src/java.base/share/classes/org/checkerframework/framework/qual/NoDefaultQualifierForUse.java index d1d1c76658d..c82472cd159 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/NoDefaultQualifierForUse.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/NoDefaultQualifierForUse.java @@ -18,6 +18,6 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface NoDefaultQualifierForUse { - /** Top qualifier in hierarchies for which no default annotation for use should be applied. */ - Class[] value() default {}; + /** Top qualifier in hierarchies for which no default annotation for use should be applied. */ + Class[] value() default {}; } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/NoQualifierParameter.java b/src/java.base/share/classes/org/checkerframework/framework/qual/NoQualifierParameter.java index 4dd970b9c73..b61b15aa44e 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/NoQualifierParameter.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/NoQualifierParameter.java @@ -32,10 +32,10 @@ @Inherited public @interface NoQualifierParameter { - /** - * Class of the top qualifier for the hierarchy for which this class has no qualifier parameter. - * - * @return the value - */ - Class[] value(); + /** + * Class of the top qualifier for the hierarchy for which this class has no qualifier parameter. + * + * @return the value + */ + Class[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/ParametricTypeVariableUseQualifier.java b/src/java.base/share/classes/org/checkerframework/framework/qual/ParametricTypeVariableUseQualifier.java new file mode 100644 index 00000000000..c5829652b90 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/ParametricTypeVariableUseQualifier.java @@ -0,0 +1,40 @@ +package org.checkerframework.framework.qual; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * A meta-annotation that indicates that an annotation can be used on a type variable use to + * explicitly indicate that the type variable is parametric in that type hierarchy. + * + *

      This is useful in combination with defaults for {@link TypeUseLocation#TYPE_VARIABLE_USE}, as + * it provides a way to have a default qualifier that expresses parametricity, which is usually + * expressed by the absence of an annotation on the type variable use. + * + *

      An annotation meta-annotated with {@code ParametricTypeVariableUseQualifier} will usually not + * be written explicitly in source code. + * + *

      This annotation is currently only for documentation, but will in the future also be used for + * automatic support for parametric type variable use qualifiers. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.ANNOTATION_TYPE}) +@AnnotatedFor("nullness") +public @interface ParametricTypeVariableUseQualifier { + /** + * Indicates which type system this annotation refers to (optional, and usually unnecessary). + * When multiple type hierarchies are supported by a single type system, then each parametric + * qualifier needs to indicate which sub-hierarchy it belongs to. Do so by passing the top + * qualifier from the given hierarchy. + * + * @return the top qualifier in the hierarchy of this qualifier + */ + // We use the meaningless Annotation.class as default value and + // then ensure there is a single top qualifier to use. + Class value() default Annotation.class; +} diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/PolymorphicQualifier.java b/src/java.base/share/classes/org/checkerframework/framework/qual/PolymorphicQualifier.java index 4e229d59e34..08580c6776a 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/PolymorphicQualifier.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/PolymorphicQualifier.java @@ -21,15 +21,15 @@ @Target({ElementType.ANNOTATION_TYPE}) @AnnotatedFor({"initialization", "nullness"}) public @interface PolymorphicQualifier { - /** - * Indicates which type system this annotation refers to (optional, and usually unnecessary). When - * multiple type hierarchies are supported by a single type system, then each polymorphic - * qualifier needs to indicate which sub-hierarchy it belongs to. Do so by passing the top - * qualifier from the given hierarchy. - * - * @return the top qualifier in the hierarchy of this qualifier - */ - // We use the meaningless Annotation.class as default value and - // then ensure there is a single top qualifier to use. - Class value() default Annotation.class; + /** + * Indicates which type system this annotation refers to (optional, and usually unnecessary). + * When multiple type hierarchies are supported by a single type system, then each polymorphic + * qualifier needs to indicate which sub-hierarchy it belongs to. Do so by passing the top + * qualifier from the given hierarchy. + * + * @return the top qualifier in the hierarchy of this qualifier + */ + // We use the meaningless Annotation.class as default value and + // then ensure there is a single top qualifier to use. + Class value() default Annotation.class; } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/PostconditionAnnotation.java b/src/java.base/share/classes/org/checkerframework/framework/qual/PostconditionAnnotation.java index 67bb434e848..1678614c67c 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/PostconditionAnnotation.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/PostconditionAnnotation.java @@ -60,10 +60,10 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.ANNOTATION_TYPE}) public @interface PostconditionAnnotation { - /** - * The qualifier that will be established as a postcondition. - * - *

      This element is analogous to {@link EnsuresQualifier#qualifier()}. - */ - Class qualifier(); + /** + * The qualifier that will be established as a postcondition. + * + *

      This element is analogous to {@link EnsuresQualifier#qualifier()}. + */ + Class qualifier(); } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/PreconditionAnnotation.java b/src/java.base/share/classes/org/checkerframework/framework/qual/PreconditionAnnotation.java index 95af23ec376..542b1fa13b4 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/PreconditionAnnotation.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/PreconditionAnnotation.java @@ -56,6 +56,6 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.ANNOTATION_TYPE}) public @interface PreconditionAnnotation { - /** The qualifier that must be established as a precondition. */ - Class qualifier(); + /** The qualifier that must be established as a precondition. */ + Class qualifier(); } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/QualifierArgument.java b/src/java.base/share/classes/org/checkerframework/framework/qual/QualifierArgument.java index e56a2800ccc..0a6810569aa 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/QualifierArgument.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/QualifierArgument.java @@ -37,10 +37,10 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface QualifierArgument { - /** - * Specifies the name of the argument of the qualifier, that is passed the values held in the - * annotated element. If the value is omitted or is empty, then the name of the annotated element - * is used as the argument name. - */ - String value() default ""; + /** + * Specifies the name of the argument of the qualifier, that is passed the values held in the + * annotated element. If the value is omitted or is empty, then the name of the annotated + * element is used as the argument name. + */ + String value() default ""; } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/QualifierForLiterals.java b/src/java.base/share/classes/org/checkerframework/framework/qual/QualifierForLiterals.java index 72cf42edf45..6c75761f602 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/QualifierForLiterals.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/QualifierForLiterals.java @@ -15,21 +15,21 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface QualifierForLiterals { - /** - * The kinds of literals whose types have this qualifier. For example, if {@code @MyAnno} is - * meta-annotated with {@code @QualifierForLiterals(LiteralKind.STRING)}, then a literal {@code - * String} constant such as {@code "hello world"} has type {@code @MyAnno String}, but occurrences - * of {@code String} in the source code are not affected. - * - *

      For String literals, also see the {@link #stringPatterns} annotation element/field. - */ - LiteralKind[] value() default {}; + /** + * The kinds of literals whose types have this qualifier. For example, if {@code @MyAnno} is + * meta-annotated with {@code @QualifierForLiterals(LiteralKind.STRING)}, then a literal {@code + * String} constant such as {@code "hello world"} has type {@code @MyAnno String}, but + * occurrences of {@code String} in the source code are not affected. + * + *

      For String literals, also see the {@link #stringPatterns} annotation element/field. + */ + LiteralKind[] value() default {}; - /** - * A string literal that matches any of these patterns has this qualifier. - * - *

      If patterns for multiple qualifiers match, then the string literal is given the greatest - * lower bound of all the matches. - */ - String[] stringPatterns() default {}; + /** + * A string literal that matches any of these patterns has this qualifier. + * + *

      If patterns for multiple qualifiers match, then the string literal is given the greatest + * lower bound of all the matches. + */ + String[] stringPatterns() default {}; } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/RelevantJavaTypes.java b/src/java.base/share/classes/org/checkerframework/framework/qual/RelevantJavaTypes.java index 667f408627e..ce53d197aa5 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/RelevantJavaTypes.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/RelevantJavaTypes.java @@ -27,17 +27,17 @@ @Target(ElementType.TYPE) @Inherited public @interface RelevantJavaTypes { - /** - * Classes where a type annotation supported by this checker may be written. - * - *

      {@code Object[].class} means that the checker processes all array types. No distinction - * among array types is currently made, and no other array class should be supplied to - * {@code @RelevantJavaTypes}. - * - *

      If a checker processes both primitive and boxed types, both must be specified separately, - * for example as {@code int.class} and {@code Integer.class}. - * - * @return classes where a type annotation supported by this checker may be written - */ - Class[] value(); + /** + * Classes where a type annotation supported by this checker may be written. + * + *

      {@code Object[].class} means that the checker processes all array types. No distinction + * among array types is currently made, and no other array class should be supplied to + * {@code @RelevantJavaTypes}. + * + *

      If a checker processes both primitive and boxed types, both must be specified separately, + * for example as {@code int.class} and {@code Integer.class}. + * + * @return classes where a type annotation supported by this checker may be written + */ + Class[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/RequiresQualifier.java b/src/java.base/share/classes/org/checkerframework/framework/qual/RequiresQualifier.java index 5b6bbab7662..2092c396e1a 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/RequiresQualifier.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/RequiresQualifier.java @@ -21,36 +21,36 @@ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) @Repeatable(RequiresQualifier.List.class) public @interface RequiresQualifier { - /** - * Returns the Java expressions for which the annotation need to be present. - * - * @return the Java expressions for which the annotation need to be present - * @checker_framework.manual #java-expressions-as-arguments Syntax of Java expressions - */ - String[] expression(); + /** + * Returns the Java expressions for which the annotation need to be present. + * + * @return the Java expressions for which the annotation need to be present + * @checker_framework.manual #java-expressions-as-arguments Syntax of Java expressions + */ + String[] expression(); - /** - * Returns the qualifier that is required. - * - * @return the qualifier that is required - */ - Class qualifier(); + /** + * Returns the qualifier that is required. + * + * @return the qualifier that is required + */ + Class qualifier(); - /** - * A wrapper annotation that makes the {@link RequiresQualifier} annotation repeatable. - * - *

      Programmers generally do not need to write this. It is created by Java when a programmer - * writes more than one {@link RequiresQualifier} annotation at the same location. - */ - @Documented - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) - public static @interface List { /** - * Returns the repeatable annotations. + * A wrapper annotation that makes the {@link RequiresQualifier} annotation repeatable. * - * @return the repeatable annotations + *

      Programmers generally do not need to write this. It is created by Java when a programmer + * writes more than one {@link RequiresQualifier} annotation at the same location. */ - RequiresQualifier[] value(); - } + @Documented + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) + public static @interface List { + /** + * Returns the repeatable annotations. + * + * @return the repeatable annotations + */ + RequiresQualifier[] value(); + } } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/StubFiles.java b/src/java.base/share/classes/org/checkerframework/framework/qual/StubFiles.java index 25d74cbda4a..64dbeff0700 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/StubFiles.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/StubFiles.java @@ -21,9 +21,9 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface StubFiles { - /** - * Stub file names. These are basenames: they include the extension (usually ".astub"), but no - * directory component. - */ - String[] value(); + /** + * Stub file names. These are basenames: they include the extension (usually ".astub"), but no + * directory component. + */ + String[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/SubtypeOf.java b/src/java.base/share/classes/org/checkerframework/framework/qual/SubtypeOf.java index 5dcb5dc3980..00059e8e607 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/SubtypeOf.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/SubtypeOf.java @@ -40,6 +40,6 @@ @Target(ElementType.ANNOTATION_TYPE) @AnnotatedFor({"initialization", "nullness"}) public @interface SubtypeOf { - /** An array of the supertype qualifiers of the annotated qualifier. */ - Class[] value(); + /** An array of the supertype qualifiers of the annotated qualifier. */ + Class[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/TargetLocations.java b/src/java.base/share/classes/org/checkerframework/framework/qual/TargetLocations.java index 704566ab8ce..d1f544e7017 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/TargetLocations.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/TargetLocations.java @@ -7,31 +7,37 @@ import java.lang.annotation.Target; /** - * NOTE: This meta-annotation is not currently - * enforced. - * - *

      A meta-annotation that restricts the type-use locations where a type qualifier may be written. + * A meta-annotation that restricts the type-use locations where a type qualifier may be applied. * When written together with {@code @Target({ElementType.TYPE_USE})}, the given type qualifier may - * be written only at locations listed in the {@code @TargetLocations(...)} meta-annotation. + * be applied only at locations listed in the {@code @TargetLocations(...)} meta-annotation. * {@code @Target({ElementType.TYPE_USE})} together with no {@code @TargetLocations(...)} means that - * the qualifier can be written on any type use. + * the qualifier can be applied to any type use. {@code @TargetLocations({})} means that the + * qualifier should not be used in source code. The same goal can be achieved by writing + * {@code @Target({})}, which is enforced by javac itself. {@code @TargetLocations({...})} is + * enforced by the checker. The resulting errors from the checker can either be suppressed using + * {@code @SuppressWarnings("type.invalid.annotations.on.location")} or can be ignored by providing + * the {@code -AignoreTargetLocations} option. * - *

      This enables a type system designer to permit a qualifier to be written only in certain + *

      This enables a type system designer to permit a qualifier to be applied only in certain * locations. For example, some type systems' top and bottom qualifier (such as {@link - * org.checkerframework.checker.nullness.qual.KeyForBottom}) should only be written on an explicit + * org.checkerframework.checker.regex.qual.RegexBottom}) should only be written on an explicit * wildcard upper or lower bound. This meta-annotation is a declarative, coarse-grained approach to * enable that. For finer-grained control, override {@code visit*} methods that visit trees in * BaseTypeVisitor. * - *

      This annotation does not prevent the type system from defaulting, inferring, or computing the - * given type annotation at the given location. It only prevents users from writing an explicit - * annotation at the given location. + *

      {@code @TargetLocations} are used for all appearances of qualifiers regardless of whether they + * are provided explicitly or implicitly (inferred or computed). Therefore, only use type-use + * locations {@code LOWER_BOUND/UPPER_BOUND} instead of the {@code IMPLICIT_XX/EXPLICIT_XX} + * alternatives. */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface TargetLocations { - /** Type uses at which the qualifier is permitted to be written in source code. */ - TypeUseLocation[] value(); + /** + * Type uses at which the qualifier is permitted to be applied in source code. + * + * @return type-use locations declared in this meta-annotation + */ + TypeUseLocation[] value(); } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/TypeKind.java b/src/java.base/share/classes/org/checkerframework/framework/qual/TypeKind.java index 9adef287c7c..e80c6fd573b 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/TypeKind.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/TypeKind.java @@ -10,66 +10,66 @@ * annotations */ public enum TypeKind { - /** Corresponds to {@link javax.lang.model.type.TypeKind#BOOLEAN} types. */ - BOOLEAN, + /** Corresponds to {@link javax.lang.model.type.TypeKind#BOOLEAN} types. */ + BOOLEAN, - /** Corresponds to {@link javax.lang.model.type.TypeKind#BYTE} types. */ - BYTE, + /** Corresponds to {@link javax.lang.model.type.TypeKind#BYTE} types. */ + BYTE, - /** Corresponds to {@link javax.lang.model.type.TypeKind#SHORT} types. */ - SHORT, + /** Corresponds to {@link javax.lang.model.type.TypeKind#SHORT} types. */ + SHORT, - /** Corresponds to {@link javax.lang.model.type.TypeKind#INT} types. */ - INT, + /** Corresponds to {@link javax.lang.model.type.TypeKind#INT} types. */ + INT, - /** Corresponds to {@link javax.lang.model.type.TypeKind#LONG} types. */ - LONG, + /** Corresponds to {@link javax.lang.model.type.TypeKind#LONG} types. */ + LONG, - /** Corresponds to {@link javax.lang.model.type.TypeKind#CHAR} types. */ - CHAR, + /** Corresponds to {@link javax.lang.model.type.TypeKind#CHAR} types. */ + CHAR, - /** Corresponds to {@link javax.lang.model.type.TypeKind#FLOAT} types. */ - FLOAT, + /** Corresponds to {@link javax.lang.model.type.TypeKind#FLOAT} types. */ + FLOAT, - /** Corresponds to {@link javax.lang.model.type.TypeKind#DOUBLE} types. */ - DOUBLE, + /** Corresponds to {@link javax.lang.model.type.TypeKind#DOUBLE} types. */ + DOUBLE, - /** Corresponds to {@link javax.lang.model.type.TypeKind#VOID} types. */ - VOID, + /** Corresponds to {@link javax.lang.model.type.TypeKind#VOID} types. */ + VOID, - /** Corresponds to {@link javax.lang.model.type.TypeKind#NONE} types. */ - NONE, + /** Corresponds to {@link javax.lang.model.type.TypeKind#NONE} types. */ + NONE, - /** Corresponds to {@link javax.lang.model.type.TypeKind#NULL} types. */ - NULL, + /** Corresponds to {@link javax.lang.model.type.TypeKind#NULL} types. */ + NULL, - /** Corresponds to {@link javax.lang.model.type.TypeKind#ARRAY} types. */ - ARRAY, + /** Corresponds to {@link javax.lang.model.type.TypeKind#ARRAY} types. */ + ARRAY, - /** Corresponds to {@link javax.lang.model.type.TypeKind#DECLARED} types. */ - DECLARED, + /** Corresponds to {@link javax.lang.model.type.TypeKind#DECLARED} types. */ + DECLARED, - /** Corresponds to {@link javax.lang.model.type.TypeKind#ERROR} types. */ - ERROR, + /** Corresponds to {@link javax.lang.model.type.TypeKind#ERROR} types. */ + ERROR, - /** Corresponds to {@link javax.lang.model.type.TypeKind#TYPEVAR} types. */ - TYPEVAR, + /** Corresponds to {@link javax.lang.model.type.TypeKind#TYPEVAR} types. */ + TYPEVAR, - /** Corresponds to {@link javax.lang.model.type.TypeKind#WILDCARD} types. */ - WILDCARD, + /** Corresponds to {@link javax.lang.model.type.TypeKind#WILDCARD} types. */ + WILDCARD, - /** Corresponds to {@link javax.lang.model.type.TypeKind#PACKAGE} types. */ - PACKAGE, + /** Corresponds to {@link javax.lang.model.type.TypeKind#PACKAGE} types. */ + PACKAGE, - /** Corresponds to {@link javax.lang.model.type.TypeKind#EXECUTABLE} types. */ - EXECUTABLE, + /** Corresponds to {@link javax.lang.model.type.TypeKind#EXECUTABLE} types. */ + EXECUTABLE, - /** Corresponds to {@link javax.lang.model.type.TypeKind#OTHER} types. */ - OTHER, + /** Corresponds to {@link javax.lang.model.type.TypeKind#OTHER} types. */ + OTHER, - /** Corresponds to {@link javax.lang.model.type.TypeKind#UNION} types. */ - UNION, + /** Corresponds to {@link javax.lang.model.type.TypeKind#UNION} types. */ + UNION, - /** Corresponds to {@link javax.lang.model.type.TypeKind#INTERSECTION} types. */ - INTERSECTION; + /** Corresponds to {@link javax.lang.model.type.TypeKind#INTERSECTION} types. */ + INTERSECTION; } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/TypeUseLocation.java b/src/java.base/share/classes/org/checkerframework/framework/qual/TypeUseLocation.java index 53039f19960..22809919f57 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/TypeUseLocation.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/TypeUseLocation.java @@ -6,83 +6,151 @@ *

      The order of enums is important. Defaults are applied in this order. In particular, this means * that OTHERWISE and ALL should be last. * + *

      For an annotation on a variable which has element kind ENUM_CONSTANT, the annotation's + * type-use location is either {@code TypeUseLocation.FIELD} or {@code + * TypeUseLocation.CONSTRUCTOR_RESULT}. + * + *

      Note: The use locations listed here are not complete, for more details see EISOP Issue #340 + * * @see DefaultQualifier * @see javax.lang.model.element.ElementKind */ public enum TypeUseLocation { - /** Apply default annotations to all unannotated raw types of fields. */ - FIELD, - - /** - * Apply default annotations to all unannotated raw types of local variables, casts, and - * instanceof. - */ - LOCAL_VARIABLE, - - /** Apply default annotations to all unannotated raw types of resource variables. */ - RESOURCE_VARIABLE, - - /** Apply default annotations to all unannotated raw types of exception parameters. */ - EXCEPTION_PARAMETER, - - /** Apply default annotations to all unannotated raw types of receiver types. */ - RECEIVER, - - /** - * Apply default annotations to all unannotated raw types of formal parameter types, excluding the - * receiver. - */ - PARAMETER, - - /** Apply default annotations to all unannotated raw types of return types. */ - RETURN, - - /** Apply default annotations to all unannotated raw types of constructor result types. */ - CONSTRUCTOR_RESULT, - - /** - * Apply default annotations to unannotated lower bounds for type variables and wildcards both - * explicit ones in {@code extends} clauses, and implicit upper bounds when no explicit {@code - * extends} or {@code super} clause is present. - */ - LOWER_BOUND, - - /** - * Apply default annotations to unannotated, but explicit lower bounds: {@code } - */ - EXPLICIT_LOWER_BOUND, - - /** - * Apply default annotations to unannotated, but implicit lower bounds: {@code } {@code }. - */ - IMPLICIT_LOWER_BOUND, - - /** - * Apply default annotations to unannotated upper bounds: both explicit ones in {@code extends} - * clauses, and implicit upper bounds when no explicit {@code extends} or {@code super} clause is - * present. - * - *

      Especially useful for parametrized classes that provide a lot of static methods with the - * same generic parameters as the class. - */ - UPPER_BOUND, - - /** - * Apply default annotations to unannotated, but explicit upper bounds: {@code }. - */ - EXPLICIT_UPPER_BOUND, - - /** Apply default annotations to unannotated type variables: {@code }. */ - IMPLICIT_UPPER_BOUND, - - /** Apply if nothing more concrete is provided. TODO: clarify relation to ALL. */ - OTHERWISE, - - /** - * Apply default annotations to all type uses other than uses of type parameters. Does not allow - * any of the other constants. Usually you want OTHERWISE. - */ - ALL; + /** Apply default annotations to unannotated top-level types of fields. */ + FIELD, + + /** + * Apply default annotations to unannotated top-level types of local variables, casts, and + * instanceof. + */ + LOCAL_VARIABLE, + + /** Apply default annotations to unannotated top-level types of resource variables. */ + RESOURCE_VARIABLE, + + /** Apply default annotations to unannotated top-level types of exception parameters. */ + EXCEPTION_PARAMETER, + + /** Apply default annotations to unannotated top-level types of receiver types. */ + RECEIVER, + + /** + * Apply default annotations to unannotated top-level types of formal parameter types, excluding + * the receiver. + */ + PARAMETER, + + /** Apply default annotations to unannotated top-level types of return types. */ + RETURN, + + /** Apply default annotations to unannotated top-level types of constructor result types. */ + CONSTRUCTOR_RESULT, + + /** + * Apply default annotations to unannotated top-level lower bounds of type parameters and + * wildcards, both explicit ones in {@code super} clauses, and implicit lower bounds when no + * explicit {@code extends} or {@code super} clause is present. + */ + LOWER_BOUND, + + /** + * Apply default annotations to unannotated top-level explicit lower bounds of wildcards: {@code + * }. Type parameters have no syntax for explicit lower bound types. + */ + EXPLICIT_LOWER_BOUND, + + /** + * Apply default annotations to unannotated implicit lower bounds of type parameters and + * wildcards: {@code } and {@code }, possibly with explicit upper bounds. + */ + // Note: no distinction between implicit lower bound when upper bound is explicit or not, in + // contrast to what we do for upper bounds. We can add that if a type system needs it. + IMPLICIT_LOWER_BOUND, + + /** + * Apply default annotations to unannotated top-level upper bounds of type parameters and + * wildcards: both explicit ones in {@code extends} clauses, and implicit upper bounds when no + * explicit {@code extends} or {@code super} clause is present. + * + *

      Especially useful for parametrized classes that provide a lot of static methods with the + * same generic parameters as the class. + */ + UPPER_BOUND, + + /** + * Apply default annotations to unannotated top-level explicit type parameter and wildcard upper + * bounds: {@code } and {@code }. + */ + EXPLICIT_UPPER_BOUND, + + /** + * Apply default annotations to unannotated top-level explicit type parameter upper bounds: + * {@code }. + */ + EXPLICIT_TYPE_PARAMETER_UPPER_BOUND, + + /** + * Apply default annotations to unannotated top-level explicit wildcard upper bounds: {@code }. + */ + EXPLICIT_WILDCARD_UPPER_BOUND, + + /** + * Apply default annotations to unannotated upper bounds of type parameters and wildcards + * without explicit upper bounds: {@code }, {@code }, and {@code }. + */ + IMPLICIT_UPPER_BOUND, + + /** + * Apply default annotations to unannotated upper bounds of type parameters without explicit + * upper bounds: {@code }. + */ + IMPLICIT_TYPE_PARAMETER_UPPER_BOUND, + + /** + * Apply default annotations to unannotated upper bounds of wildcards without a super bound: + * {@code }. + */ + IMPLICIT_WILDCARD_UPPER_BOUND_NO_SUPER, + + /** + * Apply default annotations to unannotated upper bounds of wildcards with a super bound: {@code + * }. + */ + IMPLICIT_WILDCARD_UPPER_BOUND_SUPER, + + /** + * Apply default annotations to unannotated upper bounds of wildcards with or without a super + * bound: {@code } or {@code }. + */ + IMPLICIT_WILDCARD_UPPER_BOUND, + + /** + * Apply default annotations to unannotated type variable uses that are not top-level local + * variables: {@code T field} or {@code List local}. + * + *

      Such uses of type variables are not flow-sensitively refined and are therefore usually + * parametric. + * + *

      To get parametric polymorphism: add a qualifier that is meta-annotated with {@link + * ParametricTypeVariableUseQualifier} to your type system and use it as default for {@code + * TYPE_VARIABLE_USE}, which is treated like no annotation on the type variable use. + * + *

      We could name this constant {@code TYPE_VARIABLE_USE_NOT_TOP_LEVEL_LOCAL_VARIABLE} and + * introduce a separate constant {@code TYPE_VARIABLE_USE_TOP_LEVEL_LOCAL_VARIABLE}. At the + * moment we use the {@code LOCAL_VARIABLE} default for unannotated top-level type variable uses + * of local variables: {@code T local}. + */ + TYPE_VARIABLE_USE, + + /** Apply if nothing more concrete is provided. TODO: clarify relation to ALL. */ + OTHERWISE, + + /** + * Apply default annotations to all type uses other than uses of type parameters. Does not allow + * any of the other constants. Usually you want OTHERWISE. + */ + ALL; } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/Unused.java b/src/java.base/share/classes/org/checkerframework/framework/qual/Unused.java index e431e76dc32..f0d00d15217 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/Unused.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/Unused.java @@ -39,9 +39,9 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface Unused { - /** - * The field that is annotated with @Unused may not be accessed via a receiver that is annotated - * with the "when" annotation. - */ - Class when(); + /** + * The field that is annotated with @Unused may not be accessed via a receiver that is annotated + * with the "when" annotation. + */ + Class when(); } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/UpperBoundFor.java b/src/java.base/share/classes/org/checkerframework/framework/qual/UpperBoundFor.java index f1f334242e7..75d24027f27 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/UpperBoundFor.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/UpperBoundFor.java @@ -18,7 +18,7 @@ * An example is the declaration * *

      
      - * {@literal @}DefaultFor(classes=String.class)
      + * {@literal @}UpperBoundFor(types=String.class)
        * {@literal @}interface MyAnno {}
        * 
      * @@ -31,19 +31,19 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface UpperBoundFor { - /** - * Returns {@link TypeKind}s of types that get an upper bound. The meta-annotated annotation is - * the upper bound. - * - * @return {@link TypeKind}s of types that get an upper bound - */ - TypeKind[] typeKinds() default {}; + /** + * Returns {@link TypeKind}s of types that get an upper bound. The meta-annotated annotation is + * the upper bound. + * + * @return {@link TypeKind}s of types that get an upper bound + */ + TypeKind[] typeKinds() default {}; - /** - * Returns {@link Class}es that should get an upper bound. The meta-annotated annotation is the - * upper bound. - * - * @return {@link Class}es that get an upper bound - */ - Class[] types() default {}; + /** + * Returns {@link Class}es that should get an upper bound. The meta-annotated annotation is the + * upper bound. + * + * @return {@link Class}es that get an upper bound + */ + Class[] types() default {}; } From d87bf19b4fee5e6029a3be0620e0843a7cadcf98 Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Wed, 12 Mar 2025 16:31:46 -0400 Subject: [PATCH 07/82] Remove `SideEffectsOnly` annotations (#113) --- .../share/classes/java/io/BufferedReader.java | 2 -- .../share/classes/java/lang/CharSequence.java | 3 -- .../classes/java/lang/StackStreamFactory.java | 2 -- .../classes/java/lang/StringBuilder.java | 33 +------------------ .../lang/invoke/AbstractConstantGroup.java | 2 -- src/java.base/share/classes/java/net/URL.java | 2 -- .../classes/java/nio/charset/Charset.java | 2 -- .../java/nio/file/FileTreeIterator.java | 2 -- .../share/classes/java/nio/file/Files.java | 2 -- .../share/classes/java/nio/file/Path.java | 2 -- .../share/classes/java/util/AbstractList.java | 4 --- .../share/classes/java/util/AbstractMap.java | 3 -- .../share/classes/java/util/ArrayDeque.java | 2 -- .../share/classes/java/util/ArrayList.java | 9 ----- .../share/classes/java/util/Arrays.java | 2 -- .../share/classes/java/util/Collections.java | 10 ------ .../share/classes/java/util/EnumMap.java | 1 - .../share/classes/java/util/Enumeration.java | 2 -- .../share/classes/java/util/HashMap.java | 2 -- .../share/classes/java/util/HashSet.java | 4 --- .../share/classes/java/util/Hashtable.java | 2 -- .../classes/java/util/IdentityHashMap.java | 2 -- .../java/util/ImmutableCollections.java | 5 --- .../share/classes/java/util/Iterator.java | 2 -- .../share/classes/java/util/JumboEnumSet.java | 2 -- .../classes/java/util/LinkedHashMap.java | 2 -- .../share/classes/java/util/LinkedList.java | 3 -- .../share/classes/java/util/List.java | 6 ---- .../share/classes/java/util/ListIterator.java | 2 -- .../classes/java/util/PriorityQueue.java | 2 -- .../classes/java/util/RegularEnumSet.java | 2 -- .../share/classes/java/util/Scanner.java | 19 ----------- .../classes/java/util/ServiceLoader.java | 5 --- .../share/classes/java/util/Spliterators.java | 5 --- .../share/classes/java/util/TreeMap.java | 5 --- .../share/classes/java/util/Vector.java | 3 -- .../share/classes/java/util/WeakHashMap.java | 2 -- .../util/concurrent/ArrayBlockingQueue.java | 2 -- .../util/concurrent/ConcurrentHashMap.java | 1 - .../concurrent/ConcurrentLinkedDeque.java | 2 -- .../concurrent/ConcurrentLinkedQueue.java | 2 -- .../concurrent/ConcurrentSkipListMap.java | 1 - .../util/concurrent/CopyOnWriteArrayList.java | 4 --- .../java/util/concurrent/DelayQueue.java | 2 -- .../util/concurrent/LinkedBlockingDeque.java | 2 -- .../util/concurrent/LinkedBlockingQueue.java | 2 -- .../util/concurrent/LinkedTransferQueue.java | 2 -- .../concurrent/PriorityBlockingQueue.java | 2 -- .../ScheduledThreadPoolExecutor.java | 2 -- .../classes/java/util/regex/Matcher.java | 2 -- .../classes/java/util/regex/Pattern.java | 2 -- .../share/classes/java/util/zip/ZipFile.java | 3 -- .../classes/javax/security/auth/Subject.java | 2 -- .../dataflow/qual/SideEffectsOnly.java | 29 ---------------- .../classes/sun/net/www/HeaderParser.java | 2 -- .../classes/sun/net/www/MessageHeader.java | 2 -- .../sun/security/jca/ProviderList.java | 2 -- .../share/classes/sun/util/PreHashedMap.java | 3 -- .../sun/util/locale/StringTokenIterator.java | 2 -- .../resources/ParallelListResourceBundle.java | 2 -- .../classes/java/lang/ProcessEnvironment.java | 4 --- .../sun/nio/fs/UnixDirectoryStream.java | 2 -- .../classes/sun/nio/fs/UnixFileSystem.java | 2 -- .../classes/java/lang/ProcessEnvironment.java | 3 +- .../sun/nio/fs/WindowsDirectoryStream.java | 2 -- .../classes/sun/nio/fs/WindowsFileSystem.java | 2 -- .../counter/perf/PerfInstrumentation.java | 3 -- .../jdk/internal/net/http/HeaderParser.java | 2 -- .../internal/net/http/RequestPublishers.java | 3 -- .../share/classes/java/sql/SQLException.java | 2 -- .../keys/keyresolver/KeyResolver.java | 2 -- .../keys/storage/StorageResolver.java | 2 -- .../implementations/KeyStoreResolver.java | 2 -- .../SingleCertificateResolver.java | 2 -- .../security/signature/Reference.java | 2 -- .../reference/ReferenceSubTreeData.java | 2 -- .../xml/dsig/internal/dom/DOMSubTreeData.java | 2 -- .../internal/generic/InstructionList.java | 2 -- .../internal/impl/XMLStreamFilterImpl.java | 2 -- .../internal/impl/XMLStreamReaderImpl.java | 1 - .../xerces/internal/impl/xs/XSModelImpl.java | 2 -- .../internal/impl/xs/util/XSNamedMapImpl.java | 2 -- .../impl/xs/util/XSObjectListImpl.java | 3 -- .../internal/util/NamespaceSupport.java | 2 -- .../util/XMLAttributesIteratorImpl.java | 2 -- .../xpath/internal/jaxp/XPathNodesImpl.java | 2 -- .../internal/stream/EventFilterSupport.java | 2 -- .../internal/stream/XMLEventReaderImpl.java | 2 -- .../stream/util/ReadOnlyIterator.java | 2 -- .../javax/xml/catalog/CatalogImpl.java | 2 -- .../javax/xml/stream/XMLEventReader.java | 2 -- .../javax/xml/stream/XMLStreamReader.java | 2 -- .../xml/stream/util/EventReaderDelegate.java | 2 -- .../xml/stream/util/StreamReaderDelegate.java | 1 - .../nio/cs/ext/AbstractCharsetProvider.java | 3 -- 95 files changed, 2 insertions(+), 308 deletions(-) delete mode 100644 src/java.base/share/classes/org/checkerframework/dataflow/qual/SideEffectsOnly.java diff --git a/src/java.base/share/classes/java/io/BufferedReader.java b/src/java.base/share/classes/java/io/BufferedReader.java index 61cc51b825f..0984855245f 100644 --- a/src/java.base/share/classes/java/io/BufferedReader.java +++ b/src/java.base/share/classes/java/io/BufferedReader.java @@ -38,7 +38,6 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.util.Iterator; @@ -597,7 +596,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public String next(/*@NonEmpty Iterator this*/) { if (nextLine != null || hasNext()) { String line = nextLine; diff --git a/src/java.base/share/classes/java/lang/CharSequence.java b/src/java.base/share/classes/java/lang/CharSequence.java index 6f668ed42d5..5dc55e78b4e 100644 --- a/src/java.base/share/classes/java/lang/CharSequence.java +++ b/src/java.base/share/classes/java/lang/CharSequence.java @@ -34,7 +34,6 @@ import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.util.NoSuchElementException; @@ -174,7 +173,6 @@ public boolean hasNext() { return cur < length(); } - @SideEffectsOnly("this") public int nextInt(@NonEmpty CharIterator this) { if (hasNext()) { return charAt(cur++); @@ -251,7 +249,6 @@ public boolean hasNext() { return cur < length(); } - @SideEffectsOnly("this") public int nextInt(@NonEmpty CodePointIterator this) { final int length = length(); diff --git a/src/java.base/share/classes/java/lang/StackStreamFactory.java b/src/java.base/share/classes/java/lang/StackStreamFactory.java index 3e4518da8e5..55b276e393f 100644 --- a/src/java.base/share/classes/java/lang/StackStreamFactory.java +++ b/src/java.base/share/classes/java/lang/StackStreamFactory.java @@ -26,7 +26,6 @@ import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import jdk.internal.reflect.MethodAccessor; import jdk.internal.reflect.ConstructorAccessor; import java.lang.StackWalker.Option; @@ -335,7 +334,6 @@ private int getNextBatch() { * * @see #tryNextFrame */ - @SideEffectsOnly("this") final Class nextFrame() { if (!hasNext()) { return null; diff --git a/src/java.base/share/classes/java/lang/StringBuilder.java b/src/java.base/share/classes/java/lang/StringBuilder.java index 8dfcc4a91a9..c52637c0c2e 100644 --- a/src/java.base/share/classes/java/lang/StringBuilder.java +++ b/src/java.base/share/classes/java/lang/StringBuilder.java @@ -34,7 +34,6 @@ import org.checkerframework.checker.regex.qual.PolyRegex; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import jdk.internal.vm.annotation.IntrinsicCandidate; @@ -96,7 +95,7 @@ * @see java.lang.String * @since 1.5 */ -@AnnotatedFor({"lock", "nullness", "index", "regex", "sideeffectsonly"}) +@AnnotatedFor({"lock", "nullness", "index", "regex"}) public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, Comparable, CharSequence @@ -178,14 +177,12 @@ public int compareTo(StringBuilder another) { } @Override - @SideEffectsOnly("this") public StringBuilder append(@GuardSatisfied @Nullable Object obj) { return append(String.valueOf(obj)); } @Override @IntrinsicCandidate - @SideEffectsOnly("this") public StringBuilder append(@Nullable String str) { super.append(str); return this; @@ -210,14 +207,12 @@ public StringBuilder append(@Nullable String str) { * @param sb the {@code StringBuffer} to append. * @return a reference to this object. */ - @SideEffectsOnly("this") public StringBuilder append(@Nullable StringBuffer sb) { super.append(sb); return this; } @Override - @SideEffectsOnly("this") public StringBuilder append(@Nullable CharSequence s) { super.append(s); return this; @@ -227,14 +222,12 @@ public StringBuilder append(@Nullable CharSequence s) { * @throws IndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder append(@Nullable CharSequence s, @IndexOrHigh({"#1"}) int start, @IndexOrHigh({"#1"}) int end) { super.append(s, start, end); return this; } @Override - @SideEffectsOnly("this") public StringBuilder append(char[] str) { super.append(str); return this; @@ -244,14 +237,12 @@ public StringBuilder append(char[] str) { * @throws IndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder append(char[] str, @IndexOrHigh({"#1"}) int offset, @LTLengthOf(value={"#1"}, offset={"#2 - 1"}) @NonNegative int len) { super.append(str, offset, len); return this; } @Override - @SideEffectsOnly("this") public StringBuilder append(boolean b) { super.append(b); return this; @@ -259,7 +250,6 @@ public StringBuilder append(boolean b) { @Override @IntrinsicCandidate - @SideEffectsOnly("this") public StringBuilder append(char c) { super.append(c); return this; @@ -267,28 +257,24 @@ public StringBuilder append(char c) { @Override @IntrinsicCandidate - @SideEffectsOnly("this") public StringBuilder append(int i) { super.append(i); return this; } @Override - @SideEffectsOnly("this") public StringBuilder append(long lng) { super.append(lng); return this; } @Override - @SideEffectsOnly("this") public StringBuilder append(float f) { super.append(f); return this; } @Override - @SideEffectsOnly("this") public StringBuilder append(double d) { super.append(d); return this; @@ -298,7 +284,6 @@ public StringBuilder append(double d) { * @since 1.5 */ @Override - @SideEffectsOnly("this") public StringBuilder appendCodePoint(int codePoint) { super.appendCodePoint(codePoint); return this; @@ -308,7 +293,6 @@ public StringBuilder appendCodePoint(int codePoint) { * @throws StringIndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder delete(@NonNegative int start, @NonNegative int end) { super.delete(start, end); return this; @@ -318,7 +302,6 @@ public StringBuilder delete(@NonNegative int start, @NonNegative int end) { * @throws StringIndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder deleteCharAt(@NonNegative int index) { super.deleteCharAt(index); return this; @@ -328,7 +311,6 @@ public StringBuilder deleteCharAt(@NonNegative int index) { * @throws StringIndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder replace(@NonNegative int start, @NonNegative int end, String str) { super.replace(start, end, str); return this; @@ -338,7 +320,6 @@ public StringBuilder replace(@NonNegative int start, @NonNegative int end, Strin * @throws StringIndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder insert(@NonNegative int index, char[] str, @IndexOrHigh({"#2"}) int offset, @IndexOrHigh({"#2"}) int len) { @@ -350,7 +331,6 @@ public StringBuilder insert(@NonNegative int index, char[] str, @IndexOrHigh({"# * @throws StringIndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder insert(@NonNegative int offset, @GuardSatisfied @Nullable Object obj) { super.insert(offset, obj); return this; @@ -360,7 +340,6 @@ public StringBuilder insert(@NonNegative int offset, @GuardSatisfied @Nullable O * @throws StringIndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder insert(@NonNegative int offset, @Nullable String str) { super.insert(offset, str); return this; @@ -370,7 +349,6 @@ public StringBuilder insert(@NonNegative int offset, @Nullable String str) { * @throws StringIndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder insert(@NonNegative int offset, char[] str) { super.insert(offset, str); return this; @@ -380,7 +358,6 @@ public StringBuilder insert(@NonNegative int offset, char[] str) { * @throws IndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder insert(@NonNegative int dstOffset, @Nullable CharSequence s) { super.insert(dstOffset, s); return this; @@ -390,7 +367,6 @@ public StringBuilder insert(@NonNegative int dstOffset, @Nullable CharSequence s * @throws IndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder insert(@NonNegative int dstOffset, @Nullable CharSequence s, @NonNegative int start, @NonNegative int end) { @@ -402,7 +378,6 @@ public StringBuilder insert(@NonNegative int dstOffset, @Nullable CharSequence s * @throws StringIndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder insert(@NonNegative int offset, boolean b) { super.insert(offset, b); return this; @@ -412,7 +387,6 @@ public StringBuilder insert(@NonNegative int offset, boolean b) { * @throws IndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder insert(@NonNegative int offset, char c) { super.insert(offset, c); return this; @@ -422,7 +396,6 @@ public StringBuilder insert(@NonNegative int offset, char c) { * @throws StringIndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder insert(@NonNegative int offset, int i) { super.insert(offset, i); return this; @@ -432,7 +405,6 @@ public StringBuilder insert(@NonNegative int offset, int i) { * @throws StringIndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder insert(@NonNegative int offset, long l) { super.insert(offset, l); return this; @@ -442,7 +414,6 @@ public StringBuilder insert(@NonNegative int offset, long l) { * @throws StringIndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder insert(@NonNegative int offset, float f) { super.insert(offset, f); return this; @@ -452,7 +423,6 @@ public StringBuilder insert(@NonNegative int offset, float f) { * @throws StringIndexOutOfBoundsException {@inheritDoc} */ @Override - @SideEffectsOnly("this") public StringBuilder insert(@NonNegative int offset, double d) { super.insert(offset, d); return this; @@ -483,7 +453,6 @@ public StringBuilder insert(@NonNegative int offset, double d) { } @Override - @SideEffectsOnly("this") public StringBuilder reverse() { super.reverse(); return this; diff --git a/src/java.base/share/classes/java/lang/invoke/AbstractConstantGroup.java b/src/java.base/share/classes/java/lang/invoke/AbstractConstantGroup.java index f35de4e3b3e..918f1b49163 100644 --- a/src/java.base/share/classes/java/lang/invoke/AbstractConstantGroup.java +++ b/src/java.base/share/classes/java/lang/invoke/AbstractConstantGroup.java @@ -28,7 +28,6 @@ import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.util.*; import jdk.internal.vm.annotation.Stable; @@ -103,7 +102,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public Object next(@NonEmpty AsIterator this) { int i = bumpIndex(); if (resolving) diff --git a/src/java.base/share/classes/java/net/URL.java b/src/java.base/share/classes/java/net/URL.java index e69ad14ab78..987304c4ac0 100644 --- a/src/java.base/share/classes/java/net/URL.java +++ b/src/java.base/share/classes/java/net/URL.java @@ -33,7 +33,6 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.io.File; @@ -1348,7 +1347,6 @@ public boolean hasNext() { return getNext(); } - @SideEffectsOnly("this") public URLStreamHandlerProvider next(/*@NonEmpty Iterator this*/) { if (!getNext()) throw new NoSuchElementException(); diff --git a/src/java.base/share/classes/java/nio/charset/Charset.java b/src/java.base/share/classes/java/nio/charset/Charset.java index 0064dbbcf08..0505efca2e4 100644 --- a/src/java.base/share/classes/java/nio/charset/Charset.java +++ b/src/java.base/share/classes/java/nio/charset/Charset.java @@ -28,7 +28,6 @@ import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import jdk.internal.misc.VM; import sun.nio.cs.ThreadLocalCoders; @@ -363,7 +362,6 @@ public boolean hasNext() { return getNext(); } - @SideEffectsOnly("this") public CharsetProvider next(/*@NonEmpty Iterator this*/) { if (!getNext()) throw new NoSuchElementException(); diff --git a/src/java.base/share/classes/java/nio/file/FileTreeIterator.java b/src/java.base/share/classes/java/nio/file/FileTreeIterator.java index 6bdbf899b24..d70bbd54de1 100644 --- a/src/java.base/share/classes/java/nio/file/FileTreeIterator.java +++ b/src/java.base/share/classes/java/nio/file/FileTreeIterator.java @@ -28,7 +28,6 @@ import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.io.Closeable; import java.io.IOException; @@ -112,7 +111,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public Event next(@NonEmpty FileTreeIterator this) { if (!walker.isOpen()) throw new IllegalStateException(); diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java index 1d2150d11a2..4d745a3b4fb 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -34,7 +34,6 @@ import org.checkerframework.checker.signedness.qual.PolySigned; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -3888,7 +3887,6 @@ public boolean hasNext() { throw new UncheckedIOException(e.getCause()); } } - @SideEffectsOnly("this") @Override public Path next(/*@NonEmpty Iterator this*/) { try { diff --git a/src/java.base/share/classes/java/nio/file/Path.java b/src/java.base/share/classes/java/nio/file/Path.java index 17d74768a5b..c162df157cd 100644 --- a/src/java.base/share/classes/java/nio/file/Path.java +++ b/src/java.base/share/classes/java/nio/file/Path.java @@ -30,7 +30,6 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.io.File; @@ -960,7 +959,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public Path next(/*@NonEmpty Iterator this*/) { if (i < getNameCount()) { Path result = getName(i); diff --git a/src/java.base/share/classes/java/util/AbstractList.java b/src/java.base/share/classes/java/util/AbstractList.java index a16d1a1db3b..8e1def9c98c 100644 --- a/src/java.base/share/classes/java/util/AbstractList.java +++ b/src/java.base/share/classes/java/util/AbstractList.java @@ -36,7 +36,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -389,7 +388,6 @@ public boolean hasNext() { return cursor != size(); } - @SideEffectsOnly("this") public E next(@NonEmpty Itr this) { checkForComodification(); try { @@ -875,7 +873,6 @@ public boolean hasNext() { return nextIndex() < size; } - @SideEffectsOnly("this") public E next(/*@NonEmpty ListIterator this*/) { if (hasNext()) return i.next(); @@ -888,7 +885,6 @@ public boolean hasPrevious() { return previousIndex() >= 0; } - @SideEffectsOnly("this") public E previous() { if (hasPrevious()) return i.previous(); diff --git a/src/java.base/share/classes/java/util/AbstractMap.java b/src/java.base/share/classes/java/util/AbstractMap.java index 2c58b3c3596..6d095e9892d 100644 --- a/src/java.base/share/classes/java/util/AbstractMap.java +++ b/src/java.base/share/classes/java/util/AbstractMap.java @@ -37,7 +37,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -387,7 +386,6 @@ public boolean hasNext() { return i.hasNext(); } - @SideEffectsOnly("this") public K next(/*@NonEmpty Iterator this*/) { return i.next().getKey(); } @@ -454,7 +452,6 @@ public boolean hasNext() { return i.hasNext(); } - @SideEffectsOnly("this") public V next(/*@NonEmpty Iterator this*/) { return i.next().getValue(); } diff --git a/src/java.base/share/classes/java/util/ArrayDeque.java b/src/java.base/share/classes/java/util/ArrayDeque.java index 75d6541dbd7..21ed93dd596 100644 --- a/src/java.base/share/classes/java/util/ArrayDeque.java +++ b/src/java.base/share/classes/java/util/ArrayDeque.java @@ -48,7 +48,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.io.Serializable; @@ -723,7 +722,6 @@ public final boolean hasNext() { return remaining > 0; } - @SideEffectsOnly("this") public E next(@NonEmpty DeqIterator this) { if (remaining <= 0) throw new NoSuchElementException(); diff --git a/src/java.base/share/classes/java/util/ArrayList.java b/src/java.base/share/classes/java/util/ArrayList.java index 9834cc31845..fd985d80053 100644 --- a/src/java.base/share/classes/java/util/ArrayList.java +++ b/src/java.base/share/classes/java/util/ArrayList.java @@ -40,7 +40,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -472,7 +471,6 @@ public E get(@GuardSatisfied ArrayList this, @NonNegative int index) { * @return the element previously at the specified position * @throws IndexOutOfBoundsException {@inheritDoc} */ - @SideEffectsOnly("this") public E set(@GuardSatisfied ArrayList this, @NonNegative int index, E element) { Objects.checkIndex(index, size); E oldValue = elementData(index); @@ -485,7 +483,6 @@ public E set(@GuardSatisfied ArrayList this, @NonNegative int index, E elemen * bytecode size under 35 (the -XX:MaxInlineSize default value), * which helps when add(E) is called in a C1-compiled loop. */ - @SideEffectsOnly("this") private void add(E e, Object[] elementData, int s) { if (s == elementData.length) elementData = grow(); @@ -499,7 +496,6 @@ private void add(E e, Object[] elementData, int s) { * @param e element to be appended to this list * @return {@code true} (as specified by {@link Collection#add}) */ - @SideEffectsOnly("this") @EnsuresNonEmpty("this") public boolean add(@GuardSatisfied ArrayList this, E e) { modCount++; @@ -516,7 +512,6 @@ public boolean add(@GuardSatisfied ArrayList this, E e) { * @param element element to be inserted * @throws IndexOutOfBoundsException {@inheritDoc} */ - @SideEffectsOnly("this") public void add(@GuardSatisfied ArrayList this, @NonNegative int index, E element) { rangeCheckForAdd(index); modCount++; @@ -708,7 +703,6 @@ public void clear(@GuardSatisfied ArrayList this) { * @return {@code true} if this list changed as a result of the call * @throws NullPointerException if the specified collection is null */ - @SideEffectsOnly("this") public boolean addAll(@GuardSatisfied ArrayList this, Collection c) { Object[] a = c.toArray(); modCount++; @@ -739,7 +733,6 @@ public boolean addAll(@GuardSatisfied ArrayList this, Collection * @throws IndexOutOfBoundsException {@inheritDoc} * @throws NullPointerException if the specified collection is null */ - @SideEffectsOnly("this") public boolean addAll(@GuardSatisfied ArrayList this, @NonNegative int index, Collection c) { rangeCheckForAdd(index); @@ -1010,7 +1003,6 @@ public boolean hasNext() { } @SuppressWarnings("unchecked") - @SideEffectsOnly("this") public E next(@NonEmpty Itr this) { checkForComodification(); int i = cursor; @@ -1348,7 +1340,6 @@ public boolean hasNext() { } @SuppressWarnings("unchecked") - @SideEffectsOnly("this") public E next(/*@NonEmpty ListIterator this*/) { checkForComodification(); int i = cursor; diff --git a/src/java.base/share/classes/java/util/Arrays.java b/src/java.base/share/classes/java/util/Arrays.java index 0389c3a01e1..88bb494a5c1 100644 --- a/src/java.base/share/classes/java/util/Arrays.java +++ b/src/java.base/share/classes/java/util/Arrays.java @@ -44,7 +44,6 @@ import org.checkerframework.common.value.qual.MinLen; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -4312,7 +4311,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public E next(@NonEmpty ArrayItr this) { int i = cursor; if (i >= a.length) { diff --git a/src/java.base/share/classes/java/util/Collections.java b/src/java.base/share/classes/java/util/Collections.java index 05eb4c3b698..2221172db9c 100644 --- a/src/java.base/share/classes/java/util/Collections.java +++ b/src/java.base/share/classes/java/util/Collections.java @@ -44,7 +44,6 @@ import org.checkerframework.common.value.qual.StaticallyExecutable; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -1096,7 +1095,6 @@ static class UnmodifiableCollection implements Collection, Serializable { @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() {return i.hasNext();} - @SideEffectsOnly("this") public E next(/*@NonEmpty Iterator this*/) {return i.next();} public void remove() { throw new UnsupportedOperationException(); @@ -1430,11 +1428,9 @@ public ListIterator listIterator(final int index) { @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() {return i.hasNext();} - @SideEffectsOnly("this") public E next(/*@NonEmpty ListIterator this*/) {return i.next();} @Pure public boolean hasPrevious() {return i.hasPrevious();} - @SideEffectsOnly("this") public E previous() {return i.previous();} public int nextIndex() {return i.nextIndex();} public int previousIndex() {return i.previousIndex();} @@ -1775,7 +1771,6 @@ public Iterator> iterator() { public boolean hasNext() { return i.hasNext(); } - @SideEffectsOnly("this") public Map.Entry next(/*@NonEmpty Iterator> this*/) { return new UnmodifiableEntry<>(i.next()); } @@ -3297,7 +3292,6 @@ public Iterator iterator() { @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return it.hasNext(); } - @SideEffectsOnly("this") public E next(/*@NonEmpty Iterator this*/) { return it.next(); } public void remove() { it.remove(); } public void forEachRemaining(Consumer action) { @@ -3696,7 +3690,6 @@ public ListIterator listIterator(final int index) { @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return i.hasNext(); } - @SideEffectsOnly("this") public E next(/*@NonEmpty ListIterator this*/) { return i.next(); } public boolean hasPrevious() { return i.hasPrevious(); } public E previous() { return i.previous(); } @@ -4020,7 +4013,6 @@ public Iterator> iterator() { @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return i.hasNext(); } - @SideEffectsOnly("this") public void remove() { i.remove(); } public Map.Entry next(/*@NonEmpty Iterator> this*/) { @@ -4475,7 +4467,6 @@ private static class EmptyIterator implements Iterator { @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return false; } - @SideEffectsOnly("this") public E next(@NonEmpty EmptyIterator this) { throw new NoSuchElementException(); } public void remove(@NonEmpty EmptyIterator this) { throw new IllegalStateException(); } @Override @@ -5019,7 +5010,6 @@ static Iterator singletonIterator(final E e) { public boolean hasNext() { return hasNext; } - @SideEffectsOnly("this") public E next(/*@NonEmpty Iterator this*/) { if (hasNext) { hasNext = false; diff --git a/src/java.base/share/classes/java/util/EnumMap.java b/src/java.base/share/classes/java/util/EnumMap.java index 794683ef40a..739b07174b2 100644 --- a/src/java.base/share/classes/java/util/EnumMap.java +++ b/src/java.base/share/classes/java/util/EnumMap.java @@ -39,7 +39,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; diff --git a/src/java.base/share/classes/java/util/Enumeration.java b/src/java.base/share/classes/java/util/Enumeration.java index 27b02681707..83669cc8b25 100644 --- a/src/java.base/share/classes/java/util/Enumeration.java +++ b/src/java.base/share/classes/java/util/Enumeration.java @@ -29,7 +29,6 @@ import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; /** @@ -131,7 +130,6 @@ default Iterator asIterator() { @Override public boolean hasNext() { return hasMoreElements(); } - @SideEffectsOnly("this") @Override public E next(/*@NonEmpty Iterator this*/) { return nextElement(); } diff --git a/src/java.base/share/classes/java/util/HashMap.java b/src/java.base/share/classes/java/util/HashMap.java index 0ddc8ab9e28..5a3ab1d02d6 100644 --- a/src/java.base/share/classes/java/util/HashMap.java +++ b/src/java.base/share/classes/java/util/HashMap.java @@ -39,7 +39,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -1623,7 +1622,6 @@ public final boolean hasNext() { return next != null; } - @SideEffectsOnly("this") final Node nextNode(@NonEmpty HashIterator this) { Node[] t; Node e = next; diff --git a/src/java.base/share/classes/java/util/HashSet.java b/src/java.base/share/classes/java/util/HashSet.java index 98d02eb218c..60c0692c5c2 100644 --- a/src/java.base/share/classes/java/util/HashSet.java +++ b/src/java.base/share/classes/java/util/HashSet.java @@ -36,7 +36,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.io.InvalidObjectException; @@ -238,7 +237,6 @@ public boolean contains(@GuardSatisfied HashSet this, @GuardSatisfied @Nullab * @return {@code true} if this set did not already contain the specified * element */ - @SideEffectsOnly("this") @EnsuresNonEmpty("this") public boolean add(@GuardSatisfied HashSet this, E e) { return map.put(e, PRESENT)==null; @@ -256,7 +254,6 @@ public boolean add(@GuardSatisfied HashSet this, E e) { * @param o object to be removed from this set, if present * @return {@code true} if the set contained the specified element */ - @SideEffectsOnly("this") public boolean remove(@GuardSatisfied HashSet this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { return map.remove(o)==PRESENT; } @@ -265,7 +262,6 @@ public boolean remove(@GuardSatisfied HashSet this, @GuardSatisfied @Nullable * Removes all of the elements from this set. * The set will be empty after this call returns. */ - @SideEffectsOnly("this") public void clear(@GuardSatisfied HashSet this) { map.clear(); } diff --git a/src/java.base/share/classes/java/util/Hashtable.java b/src/java.base/share/classes/java/util/Hashtable.java index 83ffa002ea2..16d89d0a9f8 100644 --- a/src/java.base/share/classes/java/util/Hashtable.java +++ b/src/java.base/share/classes/java/util/Hashtable.java @@ -39,7 +39,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -1535,7 +1534,6 @@ public boolean hasNext() { return hasMoreElements(); } - @SideEffectsOnly("this") public T next(@NonEmpty Enumerator this) { if (Hashtable.this.modCount != expectedModCount) throw new ConcurrentModificationException(); diff --git a/src/java.base/share/classes/java/util/IdentityHashMap.java b/src/java.base/share/classes/java/util/IdentityHashMap.java index 8239894e498..987652acea1 100644 --- a/src/java.base/share/classes/java/util/IdentityHashMap.java +++ b/src/java.base/share/classes/java/util/IdentityHashMap.java @@ -37,7 +37,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -761,7 +760,6 @@ public boolean hasNext() { return false; } - @SideEffectsOnly("this") protected int nextIndex(@NonEmpty IdentityHashMapIterator this) { if (modCount != expectedModCount) throw new ConcurrentModificationException(); diff --git a/src/java.base/share/classes/java/util/ImmutableCollections.java b/src/java.base/share/classes/java/util/ImmutableCollections.java index feb24ab67bb..8e382fa796e 100644 --- a/src/java.base/share/classes/java/util/ImmutableCollections.java +++ b/src/java.base/share/classes/java/util/ImmutableCollections.java @@ -34,7 +34,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.io.IOException; import java.io.InvalidObjectException; @@ -382,7 +381,6 @@ public boolean hasNext() { return cursor != size; } - @SideEffectsOnly("this") public E next(@NonEmpty ListItr this) { try { int i = cursor; @@ -856,7 +854,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") @SuppressWarnings("unchecked") public E next(/*@NonEmpty Iterator this*/) { if (idx == 1) { @@ -994,7 +991,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public E next(@NonEmpty SetNIterator this) { if (remaining > 0) { E element; @@ -1316,7 +1312,6 @@ public boolean hasNext() { return remaining > 0; } - @SideEffectsOnly("this") private int nextIndex() { int idx = this.idx; if (REVERSE) { diff --git a/src/java.base/share/classes/java/util/Iterator.java b/src/java.base/share/classes/java/util/Iterator.java index 873f17166e9..1e0d65349c6 100644 --- a/src/java.base/share/classes/java/util/Iterator.java +++ b/src/java.base/share/classes/java/util/Iterator.java @@ -29,7 +29,6 @@ import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; import org.checkerframework.framework.qual.Covariant; @@ -87,7 +86,6 @@ public interface Iterator { * @return the next element in the iteration * @throws NoSuchElementException if the iteration has no more elements */ - @SideEffectsOnly("this") E next(@GuardSatisfied @NonEmpty Iterator this); /** diff --git a/src/java.base/share/classes/java/util/JumboEnumSet.java b/src/java.base/share/classes/java/util/JumboEnumSet.java index 5ea2c67f19e..bbe9927f8fa 100644 --- a/src/java.base/share/classes/java/util/JumboEnumSet.java +++ b/src/java.base/share/classes/java/util/JumboEnumSet.java @@ -35,7 +35,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.dataflow.qual.Pure; @@ -150,7 +149,6 @@ public boolean hasNext() { @Override @SuppressWarnings("unchecked") - @SideEffectsOnly("this") public E next(@NonEmpty EnumSetIterator this) { if (!hasNext()) throw new NoSuchElementException(); diff --git a/src/java.base/share/classes/java/util/LinkedHashMap.java b/src/java.base/share/classes/java/util/LinkedHashMap.java index 4b66d66c45c..8a6b60c117a 100644 --- a/src/java.base/share/classes/java/util/LinkedHashMap.java +++ b/src/java.base/share/classes/java/util/LinkedHashMap.java @@ -36,7 +36,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.util.function.Consumer; @@ -787,7 +786,6 @@ public final boolean hasNext() { return next != null; } - @SideEffectsOnly("this") final LinkedHashMap.Entry nextNode(@NonEmpty LinkedHashIterator this) { LinkedHashMap.Entry e = next; if (modCount != expectedModCount) diff --git a/src/java.base/share/classes/java/util/LinkedList.java b/src/java.base/share/classes/java/util/LinkedList.java index 976ba956783..745be1b9b5b 100644 --- a/src/java.base/share/classes/java/util/LinkedList.java +++ b/src/java.base/share/classes/java/util/LinkedList.java @@ -39,7 +39,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -922,7 +921,6 @@ public boolean hasNext() { return nextIndex < size; } - @SideEffectsOnly("this") public E next(@NonEmpty ListItr this) { checkForComodification(); if (!hasNext()) @@ -1035,7 +1033,6 @@ private class DescendingIterator implements Iterator { public boolean hasNext() { return itr.hasPrevious(); } - @SideEffectsOnly("this") public E next(@NonEmpty DescendingIterator this) { return itr.previous(); } diff --git a/src/java.base/share/classes/java/util/List.java b/src/java.base/share/classes/java/util/List.java index 377fdfdf6ff..59c21c097f8 100644 --- a/src/java.base/share/classes/java/util/List.java +++ b/src/java.base/share/classes/java/util/List.java @@ -41,7 +41,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -297,7 +296,6 @@ public interface List extends Collection { * prevents it from being added to this list */ @ReleasesNoLocks - @SideEffectsOnly("this") @EnsuresNonEmpty("this") boolean add(@GuardSatisfied List this, E e); @@ -322,7 +320,6 @@ public interface List extends Collection { * @throws UnsupportedOperationException if the {@code remove} operation * is not supported by this list */ - @SideEffectsOnly("this") boolean remove(@GuardSatisfied List this, @UnknownSignedness Object o); @@ -370,7 +367,6 @@ public interface List extends Collection { * specified collection prevents it from being added to this list * @see #add(Object) */ - @SideEffectsOnly("this") @EnsuresNonEmptyIf(result = true, expression = "this") boolean addAll(@GuardSatisfied List this, Collection c); @@ -401,7 +397,6 @@ public interface List extends Collection { * @throws IndexOutOfBoundsException if the index is out of range * ({@code index < 0 || index > size()}) */ - @SideEffectsOnly("this") @EnsuresNonEmptyIf(result = true, expression = "this") boolean addAll(@GuardSatisfied List this, @IndexOrHigh({"this"}) int index, Collection c); @@ -657,7 +652,6 @@ default void sort(@Nullable Comparator c) { * ({@code index < 0 || index > size()}) */ @ReleasesNoLocks - @SideEffectsOnly("this") void add(@GuardSatisfied List this, @IndexOrHigh({"this"}) int index, E element); /** diff --git a/src/java.base/share/classes/java/util/ListIterator.java b/src/java.base/share/classes/java/util/ListIterator.java index d344296da53..3d53f610169 100644 --- a/src/java.base/share/classes/java/util/ListIterator.java +++ b/src/java.base/share/classes/java/util/ListIterator.java @@ -31,7 +31,6 @@ import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; /** @@ -93,7 +92,6 @@ public interface ListIterator extends Iterator { * @return the next element in the list * @throws NoSuchElementException if the iteration has no next element */ - @SideEffectsOnly("this") E next(@GuardSatisfied @NonEmpty ListIterator this); /** diff --git a/src/java.base/share/classes/java/util/PriorityQueue.java b/src/java.base/share/classes/java/util/PriorityQueue.java index 424685eade2..faa59d5f886 100644 --- a/src/java.base/share/classes/java/util/PriorityQueue.java +++ b/src/java.base/share/classes/java/util/PriorityQueue.java @@ -39,7 +39,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -544,7 +543,6 @@ public boolean hasNext() { (forgetMeNot != null && !forgetMeNot.isEmpty()); } - @SideEffectsOnly("this") public E next(@NonEmpty Itr this) { if (expectedModCount != modCount) throw new ConcurrentModificationException(); diff --git a/src/java.base/share/classes/java/util/RegularEnumSet.java b/src/java.base/share/classes/java/util/RegularEnumSet.java index 743bde6a03c..866e58fe11c 100644 --- a/src/java.base/share/classes/java/util/RegularEnumSet.java +++ b/src/java.base/share/classes/java/util/RegularEnumSet.java @@ -36,7 +36,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; /** @@ -114,7 +113,6 @@ public boolean hasNext() { return unseen != 0; } - @SideEffectsOnly("this") @SuppressWarnings("unchecked") public E next(@NonEmpty EnumSetIterator this) { if (unseen == 0) diff --git a/src/java.base/share/classes/java/util/Scanner.java b/src/java.base/share/classes/java/util/Scanner.java index e18c16a26ce..ac946fa8471 100644 --- a/src/java.base/share/classes/java/util/Scanner.java +++ b/src/java.base/share/classes/java/util/Scanner.java @@ -39,7 +39,6 @@ import org.checkerframework.common.value.qual.IntRange; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.io.*; @@ -1482,7 +1481,6 @@ public boolean hasNext(@GuardSatisfied Scanner this) { * @throws IllegalStateException if this scanner is closed * @see java.util.Iterator */ - @SideEffectsOnly("this") public String next(@GuardSatisfied @NonEmpty Scanner this) { ensureOpen(); clearCaches(); @@ -1545,7 +1543,6 @@ public boolean hasNext(@GuardSatisfied Scanner this, String pattern) { * @throws NoSuchElementException if no such tokens are available * @throws IllegalStateException if this scanner is closed */ - @SideEffectsOnly("this") public String next(@GuardSatisfied @NonEmpty Scanner this, String pattern) { return next(patternCache.forName(pattern)); } @@ -1596,7 +1593,6 @@ public boolean hasNext(@GuardSatisfied Scanner this, Pattern pattern) { * @throws NoSuchElementException if no more tokens are available * @throws IllegalStateException if this scanner is closed */ - @SideEffectsOnly("this") public String next(@GuardSatisfied @NonEmpty Scanner this, Pattern pattern) { ensureOpen(); if (pattern == null) @@ -1669,7 +1665,6 @@ public boolean hasNextLine() { * @throws NoSuchElementException if no line was found * @throws IllegalStateException if this scanner is closed */ - @SideEffectsOnly("this") public String nextLine(@GuardSatisfied @NonEmpty Scanner this) { modCount++; if (hasNextPattern == linePattern()) @@ -1919,7 +1914,6 @@ public boolean hasNextBoolean(@GuardSatisfied Scanner this) { * @throws NoSuchElementException if input is exhausted * @throws IllegalStateException if this scanner is closed */ - @SideEffectsOnly("this") public boolean nextBoolean(@GuardSatisfied @NonEmpty Scanner this) { clearCaches(); return Boolean.parseBoolean(next(boolPattern())); @@ -1986,7 +1980,6 @@ public boolean hasNextByte(@GuardSatisfied Scanner this, @Positive @IntRange(fro * @throws NoSuchElementException if input is exhausted * @throws IllegalStateException if this scanner is closed */ - @SideEffectsOnly("this") public @PolySigned byte nextByte(@GuardSatisfied @NonEmpty Scanner this) { return nextByte(defaultRadix); } @@ -2022,7 +2015,6 @@ public boolean hasNextByte(@GuardSatisfied Scanner this, @Positive @IntRange(fro * @throws IllegalStateException if this scanner is closed * @throws IllegalArgumentException if the radix is out of range */ - @SideEffectsOnly("this") public @PolySigned byte nextByte(@GuardSatisfied @NonEmpty Scanner this, @Positive @IntRange(from = 2, to = 36) int radix) { // Check cached result if ((typeCache != null) && (typeCache instanceof Byte) @@ -2106,7 +2098,6 @@ public boolean hasNextShort(@GuardSatisfied Scanner this, @Positive @IntRange(fr * @throws NoSuchElementException if input is exhausted * @throws IllegalStateException if this scanner is closed */ - @SideEffectsOnly("this") public @PolySigned short nextShort(@GuardSatisfied @NonEmpty Scanner this) { return nextShort(defaultRadix); } @@ -2142,7 +2133,6 @@ public boolean hasNextShort(@GuardSatisfied Scanner this, @Positive @IntRange(fr * @throws IllegalStateException if this scanner is closed * @throws IllegalArgumentException if the radix is out of range */ - @SideEffectsOnly("this") public @PolySigned short nextShort(@GuardSatisfied @NonEmpty Scanner this, @Positive @IntRange(from = 2, to = 36) int radix) { // Check cached result if ((typeCache != null) && (typeCache instanceof Short) @@ -2250,7 +2240,6 @@ private String processIntegerToken(String token) { * @throws NoSuchElementException if input is exhausted * @throws IllegalStateException if this scanner is closed */ - @SideEffectsOnly("this") public @PolySigned int nextInt(@GuardSatisfied @NonEmpty Scanner this) { return nextInt(defaultRadix); } @@ -2286,7 +2275,6 @@ private String processIntegerToken(String token) { * @throws IllegalStateException if this scanner is closed * @throws IllegalArgumentException if the radix is out of range */ - @SideEffectsOnly("this") public @PolySigned int nextInt(@GuardSatisfied @NonEmpty Scanner this, @Positive @IntRange(from = 2, to = 36) int radix) { // Check cached result if ((typeCache != null) && (typeCache instanceof Integer) @@ -2370,7 +2358,6 @@ public boolean hasNextLong(@GuardSatisfied Scanner this, @Positive @IntRange(fro * @throws NoSuchElementException if input is exhausted * @throws IllegalStateException if this scanner is closed */ - @SideEffectsOnly("this") public @PolySigned long nextLong(@GuardSatisfied @NonEmpty Scanner this) { return nextLong(defaultRadix); } @@ -2406,7 +2393,6 @@ public boolean hasNextLong(@GuardSatisfied Scanner this, @Positive @IntRange(fro * @throws IllegalStateException if this scanner is closed * @throws IllegalArgumentException if the radix is out of range */ - @SideEffectsOnly("this") public @PolySigned long nextLong(@GuardSatisfied @NonEmpty Scanner this, @Positive @IntRange(from = 2, to = 36) int radix) { // Check cached result if ((typeCache != null) && (typeCache instanceof Long) @@ -2532,7 +2518,6 @@ public boolean hasNextFloat(@GuardSatisfied Scanner this) { * @throws NoSuchElementException if input is exhausted * @throws IllegalStateException if this scanner is closed */ - @SideEffectsOnly("this") public float nextFloat(@GuardSatisfied @NonEmpty Scanner this) { // Check cached result if ((typeCache != null) && (typeCache instanceof Float)) { @@ -2601,7 +2586,6 @@ public boolean hasNextDouble(@GuardSatisfied Scanner this) { * @throws NoSuchElementException if the input is exhausted * @throws IllegalStateException if this scanner is closed */ - @SideEffectsOnly("this") public double nextDouble(@GuardSatisfied @NonEmpty Scanner this) { // Check cached result if ((typeCache != null) && (typeCache instanceof Double)) { @@ -2686,7 +2670,6 @@ public boolean hasNextBigInteger(@GuardSatisfied Scanner this, @IntRange(from = * @throws NoSuchElementException if the input is exhausted * @throws IllegalStateException if this scanner is closed */ - @SideEffectsOnly("this") public BigInteger nextBigInteger(@GuardSatisfied @NonEmpty Scanner this) { return nextBigInteger(defaultRadix); } @@ -2717,7 +2700,6 @@ public BigInteger nextBigInteger(@GuardSatisfied @NonEmpty Scanner this) { * @throws IllegalStateException if this scanner is closed * @throws IllegalArgumentException if the radix is out of range */ - @SideEffectsOnly("this") public BigInteger nextBigInteger(@GuardSatisfied @NonEmpty Scanner this, @IntRange(from = 2, to = 36) int radix) { // Check cached result if ((typeCache != null) && (typeCache instanceof BigInteger val) @@ -2784,7 +2766,6 @@ public boolean hasNextBigDecimal(@GuardSatisfied Scanner this) { * @throws NoSuchElementException if the input is exhausted * @throws IllegalStateException if this scanner is closed */ - @SideEffectsOnly("this") public BigDecimal nextBigDecimal(@GuardSatisfied @NonEmpty Scanner this) { // Check cached result if ((typeCache != null) && (typeCache instanceof BigDecimal val)) { diff --git a/src/java.base/share/classes/java/util/ServiceLoader.java b/src/java.base/share/classes/java/util/ServiceLoader.java index 45e6b3d9a77..fa651a75969 100644 --- a/src/java.base/share/classes/java/util/ServiceLoader.java +++ b/src/java.base/share/classes/java/util/ServiceLoader.java @@ -32,7 +32,6 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.io.BufferedReader; @@ -978,7 +977,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public Provider next(@NonEmpty LayerLookupIterator this) { if (!hasNext()) throw new NoSuchElementException(); @@ -1299,7 +1297,6 @@ public boolean hasNext() { @SuppressWarnings("removal") @Override - @SideEffectsOnly("this") public Provider next(@NonEmpty LazyClassPathLookupIterator this) { if (acc == null) { return nextService(); @@ -1330,7 +1327,6 @@ public boolean hasNext() { return (first.hasNext() || second.hasNext()); } @Override - @SideEffectsOnly("this") public Provider next(/*@NonEmpty Iterator> this*/) { if (first.hasNext()) { return first.next(); @@ -1419,7 +1415,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public S next(/*@NonEmpty Iterator this*/) { checkReloadCount(); S next; diff --git a/src/java.base/share/classes/java/util/Spliterators.java b/src/java.base/share/classes/java/util/Spliterators.java index b615c911852..29449513ee4 100644 --- a/src/java.base/share/classes/java/util/Spliterators.java +++ b/src/java.base/share/classes/java/util/Spliterators.java @@ -28,7 +28,6 @@ import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.util.function.Consumer; import java.util.function.DoubleConsumer; import java.util.function.IntConsumer; @@ -699,7 +698,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public T next(@NonEmpty Adapter this) { if (!valueReady && !hasNext()) throw new NoSuchElementException(); @@ -761,7 +759,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public int nextInt(@NonEmpty Adapter this) { if (!valueReady && !hasNext()) throw new NoSuchElementException(); @@ -819,7 +816,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public long nextLong(@NonEmpty Adapter this) { if (!valueReady && !hasNext()) throw new NoSuchElementException(); @@ -877,7 +873,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public double nextDouble(@NonEmpty Adapter this) { if (!valueReady && !hasNext()) throw new NoSuchElementException(); diff --git a/src/java.base/share/classes/java/util/TreeMap.java b/src/java.base/share/classes/java/util/TreeMap.java index e5ed54bb84e..da264a0d9eb 100644 --- a/src/java.base/share/classes/java/util/TreeMap.java +++ b/src/java.base/share/classes/java/util/TreeMap.java @@ -39,7 +39,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -1533,7 +1532,6 @@ public final boolean hasNext() { return next != null; } - @SideEffectsOnly("this") final Entry nextEntry() { Entry e = next; if (e == null) @@ -1545,7 +1543,6 @@ final Entry nextEntry() { return e; } - @SideEffectsOnly("this") final Entry prevEntry() { Entry e = next; if (e == null) @@ -2083,7 +2080,6 @@ public final boolean hasNext() { return next != null && next.key != fenceKey; } - @SideEffectsOnly("this") final TreeMap.Entry nextEntry() { TreeMap.Entry e = next; if (e == null || e.key == fenceKey) @@ -2095,7 +2091,6 @@ final TreeMap.Entry nextEntry() { return e; } - @SideEffectsOnly("this") final TreeMap.Entry prevEntry() { TreeMap.Entry e = next; if (e == null || e.key == fenceKey) diff --git a/src/java.base/share/classes/java/util/Vector.java b/src/java.base/share/classes/java/util/Vector.java index d7bd79fb888..d603fae2f34 100644 --- a/src/java.base/share/classes/java/util/Vector.java +++ b/src/java.base/share/classes/java/util/Vector.java @@ -38,7 +38,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -824,7 +823,6 @@ private void add(E e, Object[] elementData, int s) { * @return {@code true} (as specified by {@link Collection#add}) * @since 1.2 */ - @SideEffectsOnly("this") @EnsuresNonEmpty("this") public synchronized boolean add(@GuardSatisfied Vector this, E e) { modCount++; @@ -1287,7 +1285,6 @@ public boolean hasNext() { return cursor != elementCount; } - @SideEffectsOnly("this") public E next(@NonEmpty Itr this) { synchronized (Vector.this) { checkForComodification(); diff --git a/src/java.base/share/classes/java/util/WeakHashMap.java b/src/java.base/share/classes/java/util/WeakHashMap.java index fa07b1e626a..e662fcf8ca9 100644 --- a/src/java.base/share/classes/java/util/WeakHashMap.java +++ b/src/java.base/share/classes/java/util/WeakHashMap.java @@ -38,7 +38,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -833,7 +832,6 @@ public boolean hasNext() { } /** The common parts of next() across different types of iterators */ - @SideEffectsOnly("this") protected Entry nextEntry() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); diff --git a/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java index 02544fba0f9..0b22a67b0c7 100644 --- a/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java @@ -45,7 +45,6 @@ import org.checkerframework.checker.signedness.qual.PolySigned; import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.lang.ref.WeakReference; @@ -1230,7 +1229,6 @@ private void noNext() { } } - @SideEffectsOnly("this") public E next(@NonEmpty Itr this) { final E e = nextItem; if (e == null) diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java index 1dc8a8ba68c..e71bd5c2949 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java @@ -50,7 +50,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.io.ObjectStreamField; diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java index 2d8e66e2300..455ddf84ff6 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java @@ -47,7 +47,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.lang.invoke.MethodHandles; @@ -1442,7 +1441,6 @@ public boolean hasNext() { return nextItem != null; } - @SideEffectsOnly("this") public E next(@NonEmpty AbstractItr this) { E item = nextItem; if (item == null) throw new NoSuchElementException(); diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java index a8c029fdd3f..c57cb976688 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java @@ -46,7 +46,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.lang.invoke.MethodHandles; @@ -799,7 +798,6 @@ public boolean hasNext() { return nextItem != null; } - @SideEffectsOnly("this") public E next(@NonEmpty Itr this) { final Node pred = nextNode; if (pred == null) throw new NoSuchElementException(); diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java index 27572fbe95c..db027422ee8 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java @@ -47,7 +47,6 @@ import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; diff --git a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java index fb70ec0b1ab..cec8b6d32e2 100644 --- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java +++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java @@ -46,7 +46,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.lang.invoke.VarHandle; import java.lang.reflect.Field; @@ -1120,7 +1119,6 @@ public boolean hasPrevious() { } @SuppressWarnings("unchecked") - @SideEffectsOnly("this") public E next(@NonEmpty COWIterator this) { if (! hasNext()) throw new NoSuchElementException(); @@ -1128,7 +1126,6 @@ public E next(@NonEmpty COWIterator this) { } @SuppressWarnings("unchecked") - @SideEffectsOnly("this") public E previous() { if (! hasPrevious()) throw new NoSuchElementException(); @@ -1580,7 +1577,6 @@ public boolean hasNext() { return nextIndex() < size; } - @SideEffectsOnly("this") public E next(@NonEmpty COWSubListIterator this) { if (hasNext()) return it.next(); diff --git a/src/java.base/share/classes/java/util/concurrent/DelayQueue.java b/src/java.base/share/classes/java/util/concurrent/DelayQueue.java index d619b0e085f..dd0b7f4b2b1 100644 --- a/src/java.base/share/classes/java/util/concurrent/DelayQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/DelayQueue.java @@ -45,7 +45,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import static java.util.concurrent.TimeUnit.NANOSECONDS; @@ -541,7 +540,6 @@ public boolean hasNext() { } @SuppressWarnings("unchecked") - @SideEffectsOnly("this") public E next(@NonEmpty Itr this) { if (cursor >= array.length) throw new NoSuchElementException(); diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java index d25e44d2d16..732b70aa9d2 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java @@ -45,7 +45,6 @@ import org.checkerframework.checker.signedness.qual.PolySigned; import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.util.AbstractQueue; @@ -1106,7 +1105,6 @@ public boolean hasNext() { return next != null; } - @SideEffectsOnly("this") public E next(@NonEmpty AbstractItr this) { Node p; if ((p = next) == null) diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java index 4336f5a701c..a24e36f1f49 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java @@ -44,7 +44,6 @@ import org.checkerframework.checker.signedness.qual.PolySigned; import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.util.AbstractQueue; @@ -805,7 +804,6 @@ public boolean hasNext() { return next != null; } - @SideEffectsOnly("this") public E next(@NonEmpty Itr this) { Node p; if ((p = next) == null) diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java b/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java index 3fe40f13e02..0011eb385c5 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java @@ -46,7 +46,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.framework.qual.AnnotatedFor; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; @@ -922,7 +921,6 @@ public final boolean hasNext() { return nextNode != null; } - @SideEffectsOnly("this") public final E next(@NonEmpty Itr this) { final Node p; if ((p = nextNode) == null) throw new NoSuchElementException(); diff --git a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java index f615c714a28..e6ca1ad852f 100644 --- a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java @@ -45,7 +45,6 @@ import org.checkerframework.checker.signedness.qual.PolySigned; import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.lang.invoke.MethodHandles; @@ -878,7 +877,6 @@ public boolean hasNext() { return cursor < array.length; } - @SideEffectsOnly("this") public E next(@NonEmpty Itr this) { if (cursor >= array.length) throw new NoSuchElementException(); diff --git a/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java b/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java index b40a6a0ed12..d1c9a0d7fe9 100644 --- a/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java +++ b/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java @@ -43,7 +43,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.framework.qual.AnnotatedFor; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; @@ -1353,7 +1352,6 @@ public boolean hasNext() { return cursor < array.length; } - @SideEffectsOnly("this") public Runnable next(@NonEmpty Itr this) { if (cursor >= array.length) throw new NoSuchElementException(); diff --git a/src/java.base/share/classes/java/util/regex/Matcher.java b/src/java.base/share/classes/java/util/regex/Matcher.java index 0cf7838712e..378430dd590 100644 --- a/src/java.base/share/classes/java/util/regex/Matcher.java +++ b/src/java.base/share/classes/java/util/regex/Matcher.java @@ -35,7 +35,6 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import java.util.ConcurrentModificationException; @@ -1340,7 +1339,6 @@ class MatchResultIterator implements Iterator { String textAsString; @Override - @SideEffectsOnly("this") public MatchResult next(@NonEmpty MatchResultIterator this) { if (expectedCount >= 0 && expectedCount != modCount) throw new ConcurrentModificationException(); diff --git a/src/java.base/share/classes/java/util/regex/Pattern.java b/src/java.base/share/classes/java/util/regex/Pattern.java index 8c750636c56..86befd977ec 100644 --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -35,7 +35,6 @@ import org.checkerframework.common.value.qual.MinLen; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -5874,7 +5873,6 @@ class MatcherIterator implements Iterator { // > 0 if there are N next empty elements private int emptyElementCount; - @SideEffectsOnly("this") public String next(@NonEmpty MatcherIterator this) { if (!hasNext()) throw new NoSuchElementException(); diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java index 42caa2858f4..982183771c1 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -36,7 +36,6 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.signedness.qual.SignedPositive; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -515,14 +514,12 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public T nextElement(@NonEmpty ZipEntryIterator this) { return next(); } @Override @SuppressWarnings("unchecked") - @SideEffectsOnly("this") public T next(@NonEmpty ZipEntryIterator this) { synchronized (ZipFile.this) { ensureOpen(); diff --git a/src/java.base/share/classes/javax/security/auth/Subject.java b/src/java.base/share/classes/javax/security/auth/Subject.java index aff92e6ed5f..0238572b996 100644 --- a/src/java.base/share/classes/javax/security/auth/Subject.java +++ b/src/java.base/share/classes/javax/security/auth/Subject.java @@ -34,7 +34,6 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.util.*; import java.io.*; @@ -1131,7 +1130,6 @@ public Iterator iterator() { @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() {return i.hasNext();} - @SideEffectsOnly("this") public E next(/*@NonEmpty Iterator this*/) { if (which != Subject.PRIV_CREDENTIAL_SET) { return i.next(); diff --git a/src/java.base/share/classes/org/checkerframework/dataflow/qual/SideEffectsOnly.java b/src/java.base/share/classes/org/checkerframework/dataflow/qual/SideEffectsOnly.java deleted file mode 100644 index ab6a7dd1718..00000000000 --- a/src/java.base/share/classes/org/checkerframework/dataflow/qual/SideEffectsOnly.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.checkerframework.dataflow.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.JavaExpression; - -/** - * A method annotated with the declaration annotation {@code @SideEffectsOnly("A", "B")} changes the - * value of at most the expressions A and B. All other expressions have the same value before and - * after a call to the method. - * - * @checker_framework.manual #type-refinement-purity Specifying side effects - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) -public @interface SideEffectsOnly { - /** - * An upper bound on the expressions that this method might change the value of. - * - * @return the Java expressions that the annotated method might side-effect - * @checker_framework.manual #java-expressions-as-arguments Syntax of Java expressions - */ - @JavaExpression - public String[] value(); -} diff --git a/src/java.base/share/classes/sun/net/www/HeaderParser.java b/src/java.base/share/classes/sun/net/www/HeaderParser.java index 4dd84fb1e63..ca118d8ddbd 100644 --- a/src/java.base/share/classes/sun/net/www/HeaderParser.java +++ b/src/java.base/share/classes/sun/net/www/HeaderParser.java @@ -26,7 +26,6 @@ package sun.net.www; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.util.Iterator; @@ -206,7 +205,6 @@ class ParserIterator implements Iterator { public boolean hasNext () { return index next() { return new Map.Entry() { String k = i.next(); diff --git a/src/java.base/share/classes/sun/util/locale/StringTokenIterator.java b/src/java.base/share/classes/sun/util/locale/StringTokenIterator.java index 7d0ab209641..5a5edc2823f 100644 --- a/src/java.base/share/classes/sun/util/locale/StringTokenIterator.java +++ b/src/java.base/share/classes/sun/util/locale/StringTokenIterator.java @@ -31,7 +31,6 @@ package sun.util.locale; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; public class StringTokenIterator { private String text; @@ -74,7 +73,6 @@ public boolean isDone() { return done; } - @SideEffectsOnly("this") public String next() { if (hasNext()) { start = end + 1; diff --git a/src/java.base/share/classes/sun/util/resources/ParallelListResourceBundle.java b/src/java.base/share/classes/sun/util/resources/ParallelListResourceBundle.java index e372d57d222..1200d1ce217 100644 --- a/src/java.base/share/classes/sun/util/resources/ParallelListResourceBundle.java +++ b/src/java.base/share/classes/sun/util/resources/ParallelListResourceBundle.java @@ -28,7 +28,6 @@ import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.util.AbstractSet; import java.util.Collections; @@ -240,7 +239,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public String next() { if (hasNext()) { return itr.next(); diff --git a/src/java.base/unix/classes/java/lang/ProcessEnvironment.java b/src/java.base/unix/classes/java/lang/ProcessEnvironment.java index 11a552495ec..3a417dc0aba 100644 --- a/src/java.base/unix/classes/java/lang/ProcessEnvironment.java +++ b/src/java.base/unix/classes/java/lang/ProcessEnvironment.java @@ -55,7 +55,6 @@ package java.lang; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.io.*; import java.util.*; @@ -336,7 +335,6 @@ public Iterator> iterator() { Iterator> i = s.iterator(); @Pure public boolean hasNext() {return i.hasNext();} - @SideEffectsOnly("this") public Map.Entry next() { return new StringEntry(i.next()); } @@ -383,7 +381,6 @@ public Iterator iterator() { Iterator i = c.iterator(); @Pure public boolean hasNext() {return i.hasNext();} - @SideEffectsOnly("this") public String next() {return i.next().toString();} public void remove() {i.remove();} }; @@ -414,7 +411,6 @@ public Iterator iterator() { Iterator i = s.iterator(); @Pure public boolean hasNext() {return i.hasNext();} - @SideEffectsOnly("this") public String next() {return i.next().toString();} public void remove() { i.remove();} }; diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixDirectoryStream.java b/src/java.base/unix/classes/sun/nio/fs/UnixDirectoryStream.java index f462dfd2258..861abc20438 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixDirectoryStream.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixDirectoryStream.java @@ -26,7 +26,6 @@ package sun.nio.fs; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.nio.file.*; import java.util.Iterator; @@ -204,7 +203,6 @@ public synchronized boolean hasNext() { } @Override - @SideEffectsOnly("this") public synchronized Path next() { Path result; if (nextEntry == null && !atEof) { diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java index 0e514ac552d..df1dc3cf616 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java @@ -26,7 +26,6 @@ package sun.nio.fs; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.nio.file.*; import java.nio.file.attribute.*; @@ -226,7 +225,6 @@ public synchronized boolean hasNext() { } @Override - @SideEffectsOnly("this") public synchronized FileStore next() { if (next == null) next = readNext(); diff --git a/src/java.base/windows/classes/java/lang/ProcessEnvironment.java b/src/java.base/windows/classes/java/lang/ProcessEnvironment.java index 80fccfd2861..bc94244ee94 100644 --- a/src/java.base/windows/classes/java/lang/ProcessEnvironment.java +++ b/src/java.base/windows/classes/java/lang/ProcessEnvironment.java @@ -64,7 +64,7 @@ package java.lang; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; + import java.io.*; import java.util.*; @@ -145,7 +145,6 @@ public Iterator> iterator() { Iterator> i = s.iterator(); @Pure public boolean hasNext() { return i.hasNext();} - @SideEffectsOnly("this") public Map.Entry next() { return new CheckedEntry(i.next()); } diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsDirectoryStream.java b/src/java.base/windows/classes/sun/nio/fs/WindowsDirectoryStream.java index 0916f458799..bb9b70e136a 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsDirectoryStream.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsDirectoryStream.java @@ -26,7 +26,6 @@ package sun.nio.fs; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; @@ -215,7 +214,6 @@ public synchronized boolean hasNext() { } @Override - @SideEffectsOnly("this") public synchronized Path next() { Path result = null; if (nextEntry == null && !atEof) { diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystem.java b/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystem.java index 91184da6616..6db8a7248b2 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystem.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystem.java @@ -26,7 +26,6 @@ package sun.nio.fs; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.nio.file.*; import java.nio.file.attribute.*; @@ -170,7 +169,6 @@ public synchronized boolean hasNext() { } @Override - @SideEffectsOnly("this") public synchronized FileStore next() { if (next == null) next = readNext(); diff --git a/src/java.management/share/classes/sun/management/counter/perf/PerfInstrumentation.java b/src/java.management/share/classes/sun/management/counter/perf/PerfInstrumentation.java index 9091b6aa347..4e15cc326a5 100644 --- a/src/java.management/share/classes/sun/management/counter/perf/PerfInstrumentation.java +++ b/src/java.management/share/classes/sun/management/counter/perf/PerfInstrumentation.java @@ -26,8 +26,6 @@ package sun.management.counter.perf; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; - import sun.management.counter.*; import java.nio.*; @@ -85,7 +83,6 @@ boolean hasNext() { return (nextEntry < prologue.getUsed()); } - @SideEffectsOnly("this") Counter getNextCounter() { if (! hasNext()) { return null; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HeaderParser.java b/src/java.net.http/share/classes/jdk/internal/net/http/HeaderParser.java index 099f323266d..8559a5467b8 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HeaderParser.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HeaderParser.java @@ -26,7 +26,6 @@ package jdk.internal.net.http; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.util.Iterator; import java.util.Locale; @@ -208,7 +207,6 @@ public boolean hasNext () { return index= nkeys) { throw new NoSuchElementException(); diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java b/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java index 8a84c598827..1b9a9e4cad7 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java @@ -26,7 +26,6 @@ package jdk.internal.net.http; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -139,7 +138,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public ByteBuffer next() { ByteBuffer buffer = buffers.poll(); while (buffer == null) { @@ -460,7 +458,6 @@ public synchronized boolean hasNext() { } @Override - @SideEffectsOnly("this") public synchronized ByteBuffer next() { if (!hasNext()) { throw new NoSuchElementException(); diff --git a/src/java.sql/share/classes/java/sql/SQLException.java b/src/java.sql/share/classes/java/sql/SQLException.java index 1142b6c9f1e..f77ab4ffbd9 100644 --- a/src/java.sql/share/classes/java/sql/SQLException.java +++ b/src/java.sql/share/classes/java/sql/SQLException.java @@ -27,7 +27,6 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.util.Iterator; import java.util.NoSuchElementException; @@ -332,7 +331,6 @@ public boolean hasNext() { return false; } - @SideEffectsOnly("this") public Throwable next() { Throwable throwable = null; if(firstException != null){ diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java index f368cebb151..46b02eaa114 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java @@ -32,7 +32,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -302,7 +301,6 @@ public boolean hasNext() { return it.hasNext(); } - @SideEffectsOnly("this") public KeyResolverSpi next() { KeyResolverSpi resolver = it.next(); if (resolver == null) { diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/StorageResolver.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/StorageResolver.java index 18230035d56..15924ca239b 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/StorageResolver.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/StorageResolver.java @@ -23,7 +23,6 @@ package com.sun.org.apache.xml.internal.security.keys.storage; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.security.KeyStore; import java.security.cert.Certificate; @@ -151,7 +150,6 @@ public boolean hasNext() { } /** {@inheritDoc} */ - @SideEffectsOnly("this") public Certificate next() { if (hasNext()) { return currentResolver.next(); diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/KeyStoreResolver.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/KeyStoreResolver.java index 98984652a7c..4f0b44d9dc5 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/KeyStoreResolver.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/KeyStoreResolver.java @@ -23,7 +23,6 @@ package com.sun.org.apache.xml.internal.security.keys.storage.implementations; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.security.KeyStore; import java.security.KeyStoreException; @@ -112,7 +111,6 @@ public boolean hasNext() { } /** {@inheritDoc} */ - @SideEffectsOnly("this") public Certificate next() { if (hasNext()) { return this.certs.get(this.i++); diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/SingleCertificateResolver.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/SingleCertificateResolver.java index 40c1e22c689..0ccff6d0ff2 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/SingleCertificateResolver.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/SingleCertificateResolver.java @@ -23,7 +23,6 @@ package com.sun.org.apache.xml.internal.security.keys.storage.implementations; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.security.cert.Certificate; import java.security.cert.X509Certificate; @@ -81,7 +80,6 @@ public boolean hasNext() { } /** {@inheritDoc} */ - @SideEffectsOnly("this") public Certificate next() { if (this.alreadyReturned) { throw new NoSuchElementException(); diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Reference.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Reference.java index 211b5168238..dc4bbbaf960 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Reference.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Reference.java @@ -53,7 +53,6 @@ import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverContext; import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -626,7 +625,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public Node next() { return sIterator.next(); } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/reference/ReferenceSubTreeData.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/reference/ReferenceSubTreeData.java index c4ccc6336db..9d5ed1baa47 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/reference/ReferenceSubTreeData.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/reference/ReferenceSubTreeData.java @@ -31,7 +31,6 @@ import java.util.ListIterator; import java.util.NoSuchElementException; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; @@ -89,7 +88,6 @@ public boolean hasNext() { return li.hasNext(); } - @SideEffectsOnly("this") public Node next() { if (nodeSet == null) { nodeSet = dereferenceSameDocumentURI(root); diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSubTreeData.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSubTreeData.java index 78a03652f44..b893445c75c 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSubTreeData.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSubTreeData.java @@ -32,7 +32,6 @@ import java.util.ListIterator; import java.util.NoSuchElementException; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; @@ -90,7 +89,6 @@ public boolean hasNext() { return li.hasNext(); } - @SideEffectsOnly("this") public Node next() { if (nodeSet == null) { nodeSet = dereferenceSameDocumentURI(root); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java index ff99033d8ca..527210011ce 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java @@ -20,7 +20,6 @@ package com.sun.org.apache.bcel.internal.generic; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.classfile.Constant; import com.sun.org.apache.bcel.internal.util.ByteSequence; @@ -1034,7 +1033,6 @@ public Iterator iterator() { private InstructionHandle ih = start; @Override - @SideEffectsOnly("this") public InstructionHandle next() throws NoSuchElementException { if (ih == null) { throw new NoSuchElementException(); diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamFilterImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamFilterImpl.java index 6e7b4359056..7a36189f1ab 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamFilterImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamFilterImpl.java @@ -26,7 +26,6 @@ package com.sun.org.apache.xerces.internal.impl; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.StreamFilter; @@ -97,7 +96,6 @@ protected void setStreamFilter(StreamFilter sf){ * @return * @throws XMLStreamException */ - @SideEffectsOnly("this") public int next() throws XMLStreamException { if (fStreamAdvancedByHasNext && fEventAccepted) { fStreamAdvancedByHasNext = false; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamReaderImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamReaderImpl.java index efd888ab9d7..3dea188ad9b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamReaderImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamReaderImpl.java @@ -26,7 +26,6 @@ package com.sun.org.apache.xerces.internal.impl; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import com.sun.org.apache.xerces.internal.util.NamespaceContextWrapper; import com.sun.org.apache.xerces.internal.util.NamespaceSupport; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XSModelImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XSModelImpl.java index e328cd63ba0..afaafc6a7cd 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XSModelImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XSModelImpl.java @@ -21,7 +21,6 @@ package com.sun.org.apache.xerces.internal.impl.xs; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.xs.util.StringListImpl; @@ -819,7 +818,6 @@ public XSNamespaceItemListIterator(int index) { public boolean hasNext() { return (index < fGrammarCount); } - @SideEffectsOnly("this") public XSNamespaceItem next() { if (index < fGrammarCount) { return fGrammarList[index++]; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/util/XSNamedMapImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/util/XSNamedMapImpl.java index 4fc5b349dc0..29c51a220a2 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/util/XSNamedMapImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/util/XSNamedMapImpl.java @@ -21,7 +21,6 @@ package com.sun.org.apache.xerces.internal.impl.xs.util; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import com.sun.org.apache.xerces.internal.util.SymbolHash; import com.sun.org.apache.xerces.internal.xs.XSNamedMap; import com.sun.org.apache.xerces.internal.xs.XSObject; @@ -242,7 +241,6 @@ public Iterator> iterator() { public boolean hasNext() { return (index < length); } - @SideEffectsOnly("this") public Map.Entry next() { if (index < length) { return entries[index++]; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/util/XSObjectListImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/util/XSObjectListImpl.java index 1b618554f28..04f8751cfc0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/util/XSObjectListImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/util/XSObjectListImpl.java @@ -21,7 +21,6 @@ package com.sun.org.apache.xerces.internal.impl.xs.util; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import com.sun.org.apache.xerces.internal.xs.XSObject; import com.sun.org.apache.xerces.internal.xs.XSObjectList; import java.lang.reflect.Array; @@ -52,7 +51,6 @@ static class EmptyIterator implements ListIterator { public boolean hasNext() { return false; } - @SideEffectsOnly("this") public XSObject next() { throw new NoSuchElementException(); } @@ -238,7 +236,6 @@ public XSObjectListIterator(int index) { public boolean hasNext() { return (index < fLength); } - @SideEffectsOnly("this") public XSObject next() { if (index < fLength) { return fArray[index++]; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/NamespaceSupport.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/NamespaceSupport.java index 5ca84d15b1c..b6045f03eb7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/NamespaceSupport.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/NamespaceSupport.java @@ -21,7 +21,6 @@ package com.sun.org.apache.xerces.internal.util; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import com.sun.org.apache.xerces.internal.xni.NamespaceContext; import java.util.ArrayList; import java.util.Enumeration; @@ -380,7 +379,6 @@ public boolean hasNext() { /** * @see java.util.Enumeration#nextElement() */ - @SideEffectsOnly("this") public String next() { if (counter< size){ return fPrefixes[counter++]; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLAttributesIteratorImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLAttributesIteratorImpl.java index 9d04ba7cc86..e33d7cd3b85 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLAttributesIteratorImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLAttributesIteratorImpl.java @@ -26,7 +26,6 @@ package com.sun.org.apache.xerces.internal.util; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.util.Iterator; import java.util.NoSuchElementException; @@ -63,7 +62,6 @@ public boolean hasNext() { return fCurrent < getLength() ? true : false ; }//hasNext() - @SideEffectsOnly("this") public XMLAttributesImpl.Attribute next() { if(hasNext()){ // should this be of type javax.xml.stream.Attribute ? diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathNodesImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathNodesImpl.java index d48abf0d23b..37bbf74b5be 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathNodesImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathNodesImpl.java @@ -30,7 +30,6 @@ import javax.xml.xpath.XPathNodes; import javax.xml.xpath.XPathEvaluationResult.XPathResultType; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -67,7 +66,6 @@ public boolean hasNext() { return false; } - @SideEffectsOnly("this") public E next() { if (nodeList != null && nodeList.getLength() > 0) { return elementType.cast(nodeList.item(currentIndex++)); diff --git a/src/java.xml/share/classes/com/sun/xml/internal/stream/EventFilterSupport.java b/src/java.xml/share/classes/com/sun/xml/internal/stream/EventFilterSupport.java index c02d2ed2d1d..5b90d7fff0d 100644 --- a/src/java.xml/share/classes/com/sun/xml/internal/stream/EventFilterSupport.java +++ b/src/java.xml/share/classes/com/sun/xml/internal/stream/EventFilterSupport.java @@ -26,7 +26,6 @@ package com.sun.xml.internal.stream; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.util.NoSuchElementException; import javax.xml.stream.EventFilter; @@ -50,7 +49,6 @@ public EventFilterSupport(XMLEventReader eventReader, EventFilter eventFilter) { fEventFilter = eventFilter; } - @SideEffectsOnly("this") public Object next(){ try{ return nextEvent(); diff --git a/src/java.xml/share/classes/com/sun/xml/internal/stream/XMLEventReaderImpl.java b/src/java.xml/share/classes/com/sun/xml/internal/stream/XMLEventReaderImpl.java index 1f96b7112cd..3a8691698e4 100644 --- a/src/java.xml/share/classes/com/sun/xml/internal/stream/XMLEventReaderImpl.java +++ b/src/java.xml/share/classes/com/sun/xml/internal/stream/XMLEventReaderImpl.java @@ -26,7 +26,6 @@ package com.sun.xml.internal.stream; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import com.sun.xml.internal.stream.events.XMLEventAllocatorImpl; import java.util.NoSuchElementException; @@ -75,7 +74,6 @@ public boolean hasNext() { } - @SideEffectsOnly("this") public XMLEvent nextEvent() throws XMLStreamException { //if application peeked return the peeked event if(fPeekedEvent != null){ diff --git a/src/java.xml/share/classes/com/sun/xml/internal/stream/util/ReadOnlyIterator.java b/src/java.xml/share/classes/com/sun/xml/internal/stream/util/ReadOnlyIterator.java index aa1fc45aacf..dabe06ae9ab 100644 --- a/src/java.xml/share/classes/com/sun/xml/internal/stream/util/ReadOnlyIterator.java +++ b/src/java.xml/share/classes/com/sun/xml/internal/stream/util/ReadOnlyIterator.java @@ -30,7 +30,6 @@ */ import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.util.Iterator; @@ -54,7 +53,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public T next() { if(iterator != null) return iterator.next(); diff --git a/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java b/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java index e5cf4573374..a722775aabe 100644 --- a/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java +++ b/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java @@ -47,7 +47,6 @@ import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.xml.sax.SAXException; /** @@ -351,7 +350,6 @@ public boolean hasNext() { } @Override - @SideEffectsOnly("this") public Catalog next() { if (nextCatalog != null || hasNext()) { Catalog catalog = nextCatalog; diff --git a/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java b/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java index 3a951d9e3e4..f255d860246 100644 --- a/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java +++ b/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java @@ -26,7 +26,6 @@ package javax.xml.stream; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import javax.xml.stream.events.XMLEvent; @@ -54,7 +53,6 @@ public interface XMLEventReader extends Iterator { * @throws XMLStreamException if there is an error with the underlying XML. * @throws java.util.NoSuchElementException iteration has no more elements. */ - @SideEffectsOnly("this") public XMLEvent nextEvent() throws XMLStreamException; /** diff --git a/src/java.xml/share/classes/javax/xml/stream/XMLStreamReader.java b/src/java.xml/share/classes/javax/xml/stream/XMLStreamReader.java index a2067a2c8f1..8af53aff55d 100644 --- a/src/java.xml/share/classes/javax/xml/stream/XMLStreamReader.java +++ b/src/java.xml/share/classes/javax/xml/stream/XMLStreamReader.java @@ -26,7 +26,6 @@ package javax.xml.stream; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import javax.xml.namespace.NamespaceContext; import javax.xml.namespace.QName; @@ -301,7 +300,6 @@ public interface XMLStreamReader extends XMLStreamConstants { * START_ELEMENT or END_ELEMENT * @throws java.util.NoSuchElementException if this is called when hasNext() returns false */ - @SideEffectsOnly("this") public int nextTag() throws XMLStreamException; /** diff --git a/src/java.xml/share/classes/javax/xml/stream/util/EventReaderDelegate.java b/src/java.xml/share/classes/javax/xml/stream/util/EventReaderDelegate.java index f83aa47c7a2..3e3a2afe05d 100644 --- a/src/java.xml/share/classes/javax/xml/stream/util/EventReaderDelegate.java +++ b/src/java.xml/share/classes/javax/xml/stream/util/EventReaderDelegate.java @@ -26,7 +26,6 @@ package javax.xml.stream.util; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import javax.xml.stream.XMLEventReader; import javax.xml.stream.events.XMLEvent; @@ -86,7 +85,6 @@ public XMLEvent nextEvent() return reader.nextEvent(); } - @SideEffectsOnly("this") public Object next() { return reader.next(); } diff --git a/src/java.xml/share/classes/javax/xml/stream/util/StreamReaderDelegate.java b/src/java.xml/share/classes/javax/xml/stream/util/StreamReaderDelegate.java index 0865afaf040..64e332d8988 100644 --- a/src/java.xml/share/classes/javax/xml/stream/util/StreamReaderDelegate.java +++ b/src/java.xml/share/classes/javax/xml/stream/util/StreamReaderDelegate.java @@ -26,7 +26,6 @@ package javax.xml.stream.util; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; import javax.xml.namespace.QName; import javax.xml.namespace.NamespaceContext; diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java index fc0ac09f8ac..7e87a8135d1 100644 --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java @@ -26,8 +26,6 @@ package sun.nio.cs.ext; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectsOnly; - import java.lang.ref.SoftReference; import java.nio.charset.Charset; @@ -188,7 +186,6 @@ public boolean hasNext() { return i.hasNext(); } - @SideEffectsOnly("this") public Charset next() { String csn = i.next(); synchronized (AbstractCharsetProvider.this) { From 9714ebd50d4805e5a47e3729a1e77b6d6b2c74f6 Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Wed, 12 Mar 2025 23:33:30 -0400 Subject: [PATCH 08/82] Add links to refined return type logic to `j.u.Arrays#copyOf` methods (#109) Co-authored-by: Werner Dietl --- src/java.base/share/classes/java/util/Arrays.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/java.base/share/classes/java/util/Arrays.java b/src/java.base/share/classes/java/util/Arrays.java index 88bb494a5c1..9cef1cb438d 100644 --- a/src/java.base/share/classes/java/util/Arrays.java +++ b/src/java.base/share/classes/java/util/Arrays.java @@ -3520,6 +3520,8 @@ public static void fill(@PolyInterned @PolyNull @PolySigned Object[] a, @IndexOr */ @SideEffectFree @SuppressWarnings("unchecked") + @CFComment("The return type is refined when safe. See " + + "https://github.com/eisop/checker-framework/blob/17991582bc3a35509f15065b051d8e4c45c3e9ae/checker/src/main/java/org/checkerframework/checker/nullness/NullnessNoInitAnnotatedTypeFactory.java#L756") public static @Nullable T[] copyOf(T[] original, @NonNegative int newLength) { return (T[]) copyOf(original, newLength, original.getClass()); } @@ -3550,6 +3552,8 @@ public static void fill(@PolyInterned @PolyNull @PolySigned Object[] a, @IndexOr */ @SideEffectFree @IntrinsicCandidate + @CFComment("The return type is refined when safe. See " + + "https://github.com/eisop/checker-framework/blob/17991582bc3a35509f15065b051d8e4c45c3e9ae/checker/src/main/java/org/checkerframework/checker/nullness/NullnessNoInitAnnotatedTypeFactory.java#L756") public static @Nullable T[] copyOf(U[] original, @NonNegative int newLength, Class newType) { @SuppressWarnings("unchecked") T[] copy = ((Object)newType == (Object)Object[].class) From e68c028ccfd2073908ce75b84d404e9799a488e7 Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Thu, 13 Mar 2025 11:10:17 -0400 Subject: [PATCH 09/82] Remove `AnnotatedFor` on EISOP annotations (#115) --- .../checker/formatter/qual/ConversionCategory.java | 2 -- .../checker/i18nformatter/qual/I18nConversionCategory.java | 2 -- .../framework/qual/ParametricTypeVariableUseQualifier.java | 1 - .../checkerframework/framework/qual/PolymorphicQualifier.java | 1 - .../classes/org/checkerframework/framework/qual/SubtypeOf.java | 1 - 5 files changed, 7 deletions(-) diff --git a/src/java.base/share/classes/org/checkerframework/checker/formatter/qual/ConversionCategory.java b/src/java.base/share/classes/org/checkerframework/checker/formatter/qual/ConversionCategory.java index 1aae564c7d9..6e58c945d7c 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/formatter/qual/ConversionCategory.java +++ b/src/java.base/share/classes/org/checkerframework/checker/formatter/qual/ConversionCategory.java @@ -2,7 +2,6 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.framework.qual.AnnotatedFor; import java.math.BigDecimal; import java.math.BigInteger; @@ -35,7 +34,6 @@ * @checker_framework.manual #formatter-checker Format String Checker */ @SuppressWarnings("unchecked") // ".class" expressions in varargs position -@AnnotatedFor({"initialization", "nullness"}) public enum ConversionCategory { /** Use if the parameter can be of any type. Applicable for conversions b, B, h, H, s, S. */ GENERAL("bBhHsS", (Class[]) null /* everything */), diff --git a/src/java.base/share/classes/org/checkerframework/checker/i18nformatter/qual/I18nConversionCategory.java b/src/java.base/share/classes/org/checkerframework/checker/i18nformatter/qual/I18nConversionCategory.java index e8ec0a2d762..8b40222226e 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/i18nformatter/qual/I18nConversionCategory.java +++ b/src/java.base/share/classes/org/checkerframework/checker/i18nformatter/qual/I18nConversionCategory.java @@ -1,7 +1,6 @@ package org.checkerframework.checker.i18nformatter.qual; import org.checkerframework.checker.nullness.qual.Nullable; -import org.checkerframework.framework.qual.AnnotatedFor; import java.util.Arrays; import java.util.Date; @@ -22,7 +21,6 @@ * * @checker_framework.manual #i18n-formatter-checker Internationalization Format String Checker */ -@AnnotatedFor({"initialization", "nullness"}) public enum I18nConversionCategory { /** diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/ParametricTypeVariableUseQualifier.java b/src/java.base/share/classes/org/checkerframework/framework/qual/ParametricTypeVariableUseQualifier.java index c5829652b90..b0a5b392031 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/ParametricTypeVariableUseQualifier.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/ParametricTypeVariableUseQualifier.java @@ -24,7 +24,6 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.ANNOTATION_TYPE}) -@AnnotatedFor("nullness") public @interface ParametricTypeVariableUseQualifier { /** * Indicates which type system this annotation refers to (optional, and usually unnecessary). diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/PolymorphicQualifier.java b/src/java.base/share/classes/org/checkerframework/framework/qual/PolymorphicQualifier.java index 08580c6776a..e3c2573dc20 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/PolymorphicQualifier.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/PolymorphicQualifier.java @@ -19,7 +19,6 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.ANNOTATION_TYPE}) -@AnnotatedFor({"initialization", "nullness"}) public @interface PolymorphicQualifier { /** * Indicates which type system this annotation refers to (optional, and usually unnecessary). diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/SubtypeOf.java b/src/java.base/share/classes/org/checkerframework/framework/qual/SubtypeOf.java index 00059e8e607..27db9070889 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/SubtypeOf.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/SubtypeOf.java @@ -38,7 +38,6 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) -@AnnotatedFor({"initialization", "nullness"}) public @interface SubtypeOf { /** An array of the supertype qualifiers of the annotated qualifier. */ Class[] value(); From c3f95c5919f7e74a7c8c102945614b709015fe72 Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Sun, 16 Mar 2025 16:36:21 -0400 Subject: [PATCH 10/82] Check JDK consistency in CI (#117) --- .github/workflows/ci.yml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c7d88c2845d..e2820dbb0b3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -117,3 +117,36 @@ jobs: - name: Run test script checker/bin-devel/test-${{ matrix.script }}.sh run: ./checker/bin-devel/test-${{ matrix.script }}.sh working-directory: ../checker-framework + + Consistency: + name: JDK consistency on JDK ${{ matrix.java_version }} + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + java_version: [ 17 ] + env: + JAVA_VERSION: ${{ matrix.java_version }} + steps: + - uses: actions/checkout@v2 + - name: Set up JDK ${{ matrix.java_version }} + uses: actions/setup-java@v4 + with: + java-version: ${{ matrix.java_version }} + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4.1.0 + + - name: Clone plume-scripts + run: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth 1 -q https://github.com/eisop-plume-lib/plume-scripts.git + + - name: Clone git-scripts + run: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth 1 -q https://github.com/eisop-plume-lib/git-scripts.git + + - name: Clone checker-framework + run: /tmp/$USER/git-scripts/git-clone-related eisop checker-framework + + - name: Run test script checker/bin-devel/check-jdk-consistency.sh + run: ./checker/bin-devel/check-jdk-consistency.sh + working-directory: ../checker-framework From dc094144ce01dca6ec3c9cc6659f0b55b0dd192b Mon Sep 17 00:00:00 2001 From: Thomas Kirz Date: Sun, 16 Mar 2025 22:50:15 +0100 Subject: [PATCH 11/82] Annotate `java.sql.DriverManager` for nullness (#112) --- .../share/classes/java/sql/DriverManager.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/java.sql/share/classes/java/sql/DriverManager.java b/src/java.sql/share/classes/java/sql/DriverManager.java index c0e76d72c65..a9a7b21f0c9 100644 --- a/src/java.sql/share/classes/java/sql/DriverManager.java +++ b/src/java.sql/share/classes/java/sql/DriverManager.java @@ -88,7 +88,7 @@ * @see Connection * @since 1.1 */ -@AnnotatedFor({"interning"}) +@AnnotatedFor({"initialization", "nullness", "interning"}) public @UsesObjectEquals class DriverManager { @@ -226,7 +226,7 @@ public static Connection getConnection(String url, */ @CallerSensitive public static Connection getConnection(String url, - String user, String password) throws SQLException { + @Nullable String user, @Nullable String password) throws SQLException { java.util.Properties info = new java.util.Properties(); if (user != null) { @@ -386,7 +386,7 @@ public static void registerDriver(java.sql.Driver driver, * @see SecurityManager#checkPermission */ @CallerSensitive - public static void deregisterDriver(Driver driver) throws SQLException { + public static void deregisterDriver(@Nullable Driver driver) throws SQLException { if (driver == null) { return; } @@ -507,7 +507,7 @@ public static int getLoginTimeout() { * @see #getLogStream */ @Deprecated(since="1.2") - public static void setLogStream(java.io.PrintStream out) { + public static void setLogStream(java.io.@Nullable PrintStream out) { @SuppressWarnings("removal") SecurityManager sec = System.getSecurityManager(); @@ -555,12 +555,13 @@ public static void println(String message) { // Indicates whether the class object that would be created if the code calling // DriverManager is accessible. - private static boolean isDriverAllowed(Driver driver, Class caller) { + private static boolean isDriverAllowed(Driver driver, @Nullable Class caller) { ClassLoader callerCL = caller != null ? caller.getClassLoader() : null; return isDriverAllowed(driver, callerCL); } - private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) { + private static boolean isDriverAllowed(@Nullable Driver driver, + @Nullable ClassLoader classLoader) { boolean result = false; if (driver != null) { Class aClass = null; @@ -658,7 +659,7 @@ public Void run() { // Worker method called by the public getConnection() methods. private static Connection getConnection( - String url, java.util.Properties info, Class caller) throws SQLException { + String url, java.util.Properties info, @Nullable Class caller) throws SQLException { /* * When callerCl is null, we should check the application's * (which is invoking this class indirectly) @@ -724,6 +725,7 @@ private static Connection getConnection( * to avoid the capture of the Driver it being compared to as it might not * normally have access. */ +@AnnotatedFor({"initialization", "nullness"}) class DriverInfo { final Driver driver; From fed17a2ace9c492d2360357ee739998a8bb68794 Mon Sep 17 00:00:00 2001 From: Chris Povirk Date: Sun, 16 Mar 2025 19:09:50 -0400 Subject: [PATCH 12/82] Add `@Nullable` annotations to `join` and `formatted`. (#107) --- src/java.base/share/classes/java/lang/String.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index 648251dffd2..f091617a8f4 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -3379,7 +3379,7 @@ public String replace(@GuardSatisfied CharSequence target, @GuardSatisfied CharS */ @SideEffectFree @StaticallyExecutable - public static String join(CharSequence delimiter, CharSequence... elements) { + public static String join(CharSequence delimiter, @Nullable CharSequence... elements) { var delim = delimiter.toString(); var elems = new String[elements.length]; for (int i = 0; i < elements.length; i++) { @@ -3475,7 +3475,7 @@ static String join(String prefix, String suffix, String delimiter, String[] elem @SideEffectFree @StaticallyExecutable public static String join(CharSequence delimiter, - Iterable elements) { + Iterable elements) { Objects.requireNonNull(delimiter); Objects.requireNonNull(elements); var delim = delimiter.toString(); @@ -4393,7 +4393,7 @@ public static String format(@GuardSatisfied @Nullable Locale l, String format, @ * */ @SideEffectFree - public String formatted(Object... args) { + public String formatted(@Nullable Object... args) { return new Formatter().format(this, args).toString(); } From 9fdc6987d7f2893c0aa6ffcacf4fcb11aef42af2 Mon Sep 17 00:00:00 2001 From: Chris Povirk Date: Sun, 16 Mar 2025 21:10:17 -0400 Subject: [PATCH 13/82] Annotate `Record` for nullness. (#108) Co-authored-by: Werner Dietl --- src/java.base/share/classes/java/lang/Record.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/lang/Record.java b/src/java.base/share/classes/java/lang/Record.java index b81674db188..46893bccaa3 100644 --- a/src/java.base/share/classes/java/lang/Record.java +++ b/src/java.base/share/classes/java/lang/Record.java @@ -26,6 +26,8 @@ import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.signedness.qual.UnknownSignedness; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; /** * This is the common base class of all Java language record classes. @@ -89,6 +91,7 @@ * @jls 8.10 Record Types * @since 16 */ +@AnnotatedFor({"initialization", "nullness"}) public abstract class Record { /** * Constructor for record classes to call. @@ -142,7 +145,7 @@ protected Record() {} * argument; {@code false} otherwise. */ @Override - public abstract boolean equals(@GuardSatisfied Record this, @GuardSatisfied Object obj); + public abstract boolean equals(@GuardSatisfied Record this, @GuardSatisfied @Nullable Object obj); /** * Returns a hash code value for the record. From 8748294e4b62ad3c001713c3192a918e8cea858f Mon Sep 17 00:00:00 2001 From: Chris Povirk Date: Sun, 16 Mar 2025 21:40:32 -0400 Subject: [PATCH 14/82] Use `@NonNull` more for "the value inside the `Optional`." (#110) --- src/java.base/share/classes/java/util/Optional.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/java.base/share/classes/java/util/Optional.java b/src/java.base/share/classes/java/util/Optional.java index 49fec47b44e..eb5fcd0d8d5 100644 --- a/src/java.base/share/classes/java/util/Optional.java +++ b/src/java.base/share/classes/java/util/Optional.java @@ -216,7 +216,7 @@ public boolean isEmpty() { * {@code null} */ @OptionalEliminator - public void ifPresent(Consumer action) { + public void ifPresent(Consumer action) { if (value != null) { action.accept(value); } @@ -235,7 +235,7 @@ public void ifPresent(Consumer action) { * @since 9 */ @OptionalEliminator - public void ifPresentOrElse(Consumer action, Runnable emptyAction) { + public void ifPresentOrElse(Consumer action, Runnable emptyAction) { if (value != null) { action.accept(value); } else { @@ -255,7 +255,7 @@ public void ifPresentOrElse(Consumer action, Runnable emptyAction) { * @throws NullPointerException if the predicate is {@code null} */ @OptionalPropagator - public Optional filter(Predicate predicate) { + public Optional filter(Predicate predicate) { Objects.requireNonNull(predicate); if (!isPresent()) { return this; @@ -300,7 +300,7 @@ public Optional filter(Predicate predicate) { @CFComment({"@SideEffectFree: the mapper must not have side effects."}) @OptionalPropagator @SideEffectFree - public Optional map(Function mapper) { + public Optional map(Function mapper) { Objects.requireNonNull(mapper); if (!isPresent()) { return empty(); @@ -329,7 +329,7 @@ public Optional map(Function mapper) { * returns a {@code null} result */ @OptionalPropagator - public Optional flatMap(Function> mapper) { + public Optional flatMap(Function> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) { return empty(); @@ -381,7 +381,7 @@ public Optional or(Supplier> supplier) { * @since 9 */ @SideEffectFree - public Stream stream() { + public Stream<@NonNull T> stream() { if (!isPresent()) { return Stream.empty(); } else { From cabe8f7161e05d605a15a3f0bcc60091fb2378c4 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 1 Apr 2025 14:56:32 -0700 Subject: [PATCH 15/82] Use JDK 21 for CF tests in CI, and define SQL Quotes qualifiers --- azure-pipelines.yml | 4 +-- configure | 0 src/java.base/share/classes/module-info.java | 1 + .../checker/sqlquotes/qual/SqlEvenQuotes.java | 27 +++++++++++++++++ .../checker/sqlquotes/qual/SqlOddQuotes.java | 29 +++++++++++++++++++ .../sqlquotes/qual/SqlQuotesBottom.java | 27 +++++++++++++++++ .../sqlquotes/qual/SqlQuotesUnknown.java | 25 ++++++++++++++++ .../share/classes/java/sql/Statement.java | 2 +- 8 files changed, 112 insertions(+), 3 deletions(-) mode change 100644 => 100755 configure create mode 100644 src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e053f2470e7..a1cfd12516f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -157,11 +157,11 @@ jobs: - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh) displayName: test-typecheck.sh -- job: test_cftests_all_jdk20 +- job: test_cftests_all_jdk21 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' - container: mdernst/cf-ubuntu-jdk20:latest + container: mdernst/cf-ubuntu-jdk21:latest steps: - checkout: self fetchDepth: 25 diff --git a/configure b/configure old mode 100644 new mode 100755 diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index 99ee6786fea..8713a624dc0 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -96,6 +96,7 @@ exports org.checkerframework.checker.regex.qual; exports org.checkerframework.checker.signature.qual; exports org.checkerframework.checker.signedness.qual; + exports org.checkerframework.checker.sqlquotes.qual; exports org.checkerframework.checker.tainting.qual; exports org.checkerframework.checker.units.qual; exports org.checkerframework.common.aliasing.qual; diff --git a/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java b/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java new file mode 100644 index 00000000000..20da1db881f --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java @@ -0,0 +1,27 @@ +package org.checkerframework.checker.sqlquotes.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Denotes a String that contains either zero or an even number of unescaped single quotes — + * i.e., there must be either zero or an even number of {@code '} characters in a SqlEvenQuotes + * String that are not preceded immediately by another {@code '} character. (Thus, all SqlEvenQuotes + * Strings ultimately contain an even number of {@code '} characters.) A SqlEvenQuotes String is + * syntactical to be passed to query execution methods and is guaranteed not to affect whether + * subsequent concatenations are interpreted as SQL command code or as SQL query values. + * + *

      Common use cases include: SQL query fragments, such as "SELECT * FROM"; properly sanitized + * user input; and complete SQL queries, such as "SELECT * FROM table WHERE field = 'value'". + * + * @checker_framework.manual #sql-quotes-checker SQL Quotes Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQuotesUnknown.class) +public @interface SqlEvenQuotes {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java b/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java new file mode 100644 index 00000000000..05a6c99d42f --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java @@ -0,0 +1,29 @@ +package org.checkerframework.checker.sqlquotes.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Denotes a String that contains an odd number of unescaped single quotes -- i.e., there must be an + * odd number of ' characters in a SqlOddQuotes String that are not preceded immediately by another + * ' character. (Thus, all SqlOddQuotes Strings ultimately contain an odd number of single quotes, + * escaped or otherwise.) SqlOddQuotes Strings are not syntactical to be passed to query execution + * methods. + * + *

      Common use cases include: SQL query fragments to be concatenated with user input, such as + * "SELECT * FROM table WHERE field = '"; SQL query fragments containing user input but missing an + * ending single quote, such as "SELECT * FROM table WHERE field = 'value"; connecting punctuation, + * such as "', "; and any combinations of the above with paired-off single quotes, such as "SELECT * + * FROM table WHERE field1 = 'value1', field2 = 'value2', field3 = '". + * + * @checker_framework.manual #sql-quotes-checker SQL Quotes Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQuotesUnknown.class) +public @interface SqlOddQuotes {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java b/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java new file mode 100644 index 00000000000..41acaca1641 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java @@ -0,0 +1,27 @@ +package org.checkerframework.checker.sqlquotes.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultFor; +import org.checkerframework.framework.qual.InvisibleQualifier; +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TargetLocations; +import org.checkerframework.framework.qual.TypeUseLocation; + +/** + * Represents the bottom of the SQL Quotes qualifier hierarchy. + * + * @checker_framework.manual #sql-quotes-checker SQL Quotes Checker + * @checker_framework.manual #bottom-type the bottom type + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@InvisibleQualifier +@SubtypeOf({SqlEvenQuotes.class, SqlOddQuotes.class}) +@DefaultFor(value = {TypeUseLocation.LOWER_BOUND}) +public @interface SqlQuotesBottom {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java b/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java new file mode 100644 index 00000000000..ad3cb4ff049 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java @@ -0,0 +1,25 @@ +package org.checkerframework.checker.sqlquotes.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Represents the top of the SQL Quotes qualifier hierarchy. Used to denote a String of which the + * quoting is unknown. Using a SqlQuotesUnknown Strings within a SQL query may be, or lead to, a SQL + * injection vulnerability. + * + *

      Common use cases include unsanitized user input. + * + * @checker_framework.manual #sql-quotes-checker SQL Quotes Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({}) +@DefaultQualifierInHierarchy +public @interface SqlQuotesUnknown {} diff --git a/src/java.sql/share/classes/java/sql/Statement.java b/src/java.sql/share/classes/java/sql/Statement.java index 41a15595553..ad0fd5e92dc 100644 --- a/src/java.sql/share/classes/java/sql/Statement.java +++ b/src/java.sql/share/classes/java/sql/Statement.java @@ -69,7 +69,7 @@ public interface Statement extends Wrapper, AutoCloseable { * method has been exceeded and has at least attempted to cancel * the currently running {@code Statement} */ - ResultSet executeQuery(@Untainted @SqlEvenQuotes @SqlEvenQuotes String sql) throws SQLException; + ResultSet executeQuery(@Untainted @SqlEvenQuotes String sql) throws SQLException; /** * Executes the given SQL statement, which may be an {@code INSERT}, From fbf40418665b786c3c432e418756474665642ccc Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Tue, 13 May 2025 16:05:00 -0400 Subject: [PATCH 16/82] Always run Gradle on JDK 21; also run CI tests on JDK 25 (#124) Co-authored-by: Werner Dietl --- .github/workflows/ci.yml | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e2820dbb0b3..4f4b3a1c150 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,9 +1,8 @@ name: CI tests on: - push: - branches: [ "master" ] pull_request: + push: branches: [ "master" ] concurrency: @@ -48,20 +47,29 @@ jobs: strategy: matrix: script: ['cftests-junit', 'cftests-nonjunit'] - java_version: [8, 11, 17, 21, 23] + java_version: ['8', '11', '17', '21', '24', '25-ea'] continue-on-error: true env: JAVA_VERSION: ${{ matrix.java_version }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + + - name: Set up JDK 21 for Gradle to run on + uses: actions/setup-java@v4 + with: + # Install JDK 21 first, to make it available to Gradle using `gradle.properties` below. + java-version: '21' + distribution: 'temurin' - name: Set up JDK ${{ matrix.java_version }} uses: actions/setup-java@v4 with: java-version: ${{ matrix.java_version }} distribution: 'temurin' - + - name: Inject JAVA_HOME_21_64 into `gradle.properties` to always use JDK 21 for Gradle + run: mkdir ~/.gradle && echo "org.gradle.java.home=$JAVA_HOME_21_X64" >> ~/.gradle/gradle.properties + - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4.1.0 + uses: gradle/actions/setup-gradle@v4.3.1 - name: Setup Bazel uses: bazel-contrib/setup-bazel@0.9.0 @@ -83,6 +91,8 @@ jobs: - name: Run test script checker/bin-devel/test-${{ matrix.script }}.sh run: ./checker/bin-devel/test-${{ matrix.script }}.sh working-directory: ../checker-framework + env: + ORG_GRADLE_PROJECT_useJdkVersion: ${{ matrix.java_version }} extra: name: ${{ matrix.script }} on JDK ${{ matrix.java_version }} @@ -91,11 +101,12 @@ jobs: fail-fast: true matrix: script: ['plume-lib', 'daikon'] - java_version: [17] + java_version: ['21'] env: JAVA_VERSION: ${{ matrix.java_version }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - name: Set up JDK ${{ matrix.java_version }} uses: actions/setup-java@v4 with: @@ -124,7 +135,7 @@ jobs: strategy: fail-fast: true matrix: - java_version: [ 17 ] + java_version: ['21'] env: JAVA_VERSION: ${{ matrix.java_version }} steps: From 606f06ac0140059a6f8274860b92ec3c8fc8c603 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sat, 31 May 2025 08:33:26 -0700 Subject: [PATCH 17/82] Relax types in `Map.merge()` --- src/java.base/share/classes/java/util/Map.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/java.base/share/classes/java/util/Map.java b/src/java.base/share/classes/java/util/Map.java index 225046c738a..a4accc42e81 100644 --- a/src/java.base/share/classes/java/util/Map.java +++ b/src/java.base/share/classes/java/util/Map.java @@ -1174,8 +1174,8 @@ default boolean replace(K key, V oldValue, V newValue) { * (optional) * @since 1.8 */ - default @PolyNull V computeIfPresent(K key, - BiFunction remappingFunction) { + default @Nullable V computeIfPresent(K key, + BiFunction remappingFunction) { Objects.requireNonNull(remappingFunction); V oldValue; if ((oldValue = get(key)) != null) { @@ -1260,8 +1260,8 @@ default boolean replace(K key, V oldValue, V newValue) { * (optional) * @since 1.8 */ - default @PolyNull V compute(K key, - BiFunction remappingFunction) { + default @Nullable V compute(K key, + BiFunction remappingFunction) { Objects.requireNonNull(remappingFunction); V oldValue = get(key); @@ -1358,12 +1358,8 @@ default boolean replace(K key, V oldValue, V newValue) { * null * @since 1.8 */ - @CFComment({ - "It would be more flexible to make the return type of remappingFunction be `@Nullable V`. A", - "remappingFunction that returns null is is probably rare, and these annotations accommodate", - "the majority of uses that don't return null."}) - default @PolyNull V merge(K key, @NonNull V value, - BiFunction remappingFunction) { + default @Nullable V merge(K key, @NonNull V value, + BiFunction remappingFunction) { Objects.requireNonNull(remappingFunction); Objects.requireNonNull(value); V oldValue = get(key); From f8c0ed8797b9317a96280cfd9dc50277b7b71064 Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Fri, 27 Jun 2025 18:36:52 -0400 Subject: [PATCH 18/82] Run CI daily (#125) --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f4b3a1c150..6de18c92f96 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,8 @@ name: CI tests on: + schedule: + - cron: '0 7 * * *' # Runs daily at 2:00 AM EST pull_request: push: branches: [ "master" ] From 16df476ca692e62717f60dea6b109ebe1ac0ecc2 Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Thu, 3 Jul 2025 21:00:55 -0400 Subject: [PATCH 19/82] Make consistent with changes in https://github.com/eisop/checker-framework/pull/1303 --- .../qual/EnsuresCalledMethodsOnException.java | 2 +- .../framework/qual/InheritedAnnotation.java | 9 +++++++-- .../framework/qual/InvisibleQualifier.java | 20 +++++++++++++++++-- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsOnException.java b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsOnException.java index 5d2d7e6f26c..c561433cd86 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsOnException.java +++ b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsOnException.java @@ -64,7 +64,7 @@ // /** // * Returns the exception types under which the postcondition holds. // * - // * @return the exception types under which the postcondition holds. + // * @return the exception types under which the postcondition holds // */ // Class[] exceptions(); diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/InheritedAnnotation.java b/src/java.base/share/classes/org/checkerframework/framework/qual/InheritedAnnotation.java index cd1db57dc26..7f82c0176e0 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/InheritedAnnotation.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/InheritedAnnotation.java @@ -7,8 +7,13 @@ import java.lang.annotation.Target; /** - * A meta-annotation that specifies if a declaration annotation should be inherited. This should not - * be written on type annotations. + * A meta-annotation that specifies that a declaration annotation should be inherited. This should + * not be written on type annotations. Unlike {@link java.lang.annotation.Inherited}, this + * meta-annotation causes the declaration annotation to be inherited even if it is used to annotate + * something other than a class. + * + *

      If an annotation type is meta-annotation with {@link java.lang.annotation.Inherited}, that + * annotation will only be inherited when written on a class. */ @Documented @Retention(RetentionPolicy.RUNTIME) diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/InvisibleQualifier.java b/src/java.base/share/classes/org/checkerframework/framework/qual/InvisibleQualifier.java index 1925dc085d0..45b0f3684c8 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/InvisibleQualifier.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/InvisibleQualifier.java @@ -7,8 +7,24 @@ import java.lang.annotation.Target; /** - * A meta-annotation indicating that an annotation is a type qualifier that should not be visible in - * output. + * A meta-annotation indicating that an annotation is a type qualifier that should not be shown in + * output. {@code @InvisibleQualifier} should only be written on a qualifier that is also + * meta-annotated with {@code @}{@link DefaultQualifierInHierarchy}. + * + *

      By default, the Checker Framework's error messages show every annotation, including inferred + * and default ones (which far outnumber the ones explicitly written by the programmer). Being + * explicit helps users understand the effective annotations, which the Checker Framework operates + * upon. However, the output can be verbose, and it can show annotations that a user should not + * write. For example, a Compiler Message Key Checker warning message might contain + * "{@code @UnknownCompilerMessageKey Map<@CompilerMessageKey String, @UnknownCompilerMessageKey + * String>}". + * + *

      When an annotation is meta-annotated with {@code @InvisibleQualifier}, then the Checker + * Framework does not print the given qualifier when printing types. For the above example, the + * Compiler Message Key Checker prints "{@code Map<@CompilerMessageKey String, String>}". + * + *

      If a user runs the Checker Framework with command-line argument {@code -AprintAllQualifiers}, + * then invisible qualifiers are output. */ @Documented @Retention(RetentionPolicy.RUNTIME) From 71e71e472d7a4bfd3b0d0074ed9518d8452dc2cd Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Wed, 6 Aug 2025 13:14:18 -0700 Subject: [PATCH 20/82] Refresh qualifier definitions --- README.md | 2 +- checker-qual.jar | Bin 237226 -> 272438 bytes src/java.base/share/classes/module-info.java | 2 +- .../qual/EnsuresCalledMethods.java | 2 +- .../qual/EnsuresCalledMethodsIf.java | 2 +- .../qual/EnsuresCalledMethodsOnException.java | 8 ++--- ....java => EnsuresCalledMethodsVarargs.java} | 4 +-- .../qual/I18nConversionCategory.java | 2 +- .../checker/index/qual/EnsuresLTLengthOf.java | 10 ++++--- .../index/qual/EnsuresLTLengthOfIf.java | 2 +- .../checker/index/qual/IndexFor.java | 2 +- .../checker/lock/qual/EnsuresLockHeld.java | 2 +- .../checker/lock/qual/EnsuresLockHeldIf.java | 2 +- .../mustcall/qual/CreatesMustCallFor.java | 2 +- .../checker/mustcall/qual/MustCall.java | 6 ++-- .../mustcall/qual/MustCallUnknown.java | 6 ++-- .../checker/nonempty/qual/NonEmpty.java | 5 ++-- .../nonempty/qual/UnknownNonEmpty.java | 3 +- .../checker/optional/qual/EnsuresPresent.java | 4 +-- .../checker/optional/qual/OptionalBottom.java | 20 ------------- .../qual/BinaryNameWithoutPackage.java | 28 ------------------ .../checker/signature/qual/Identifier.java | 6 +--- .../qual/EnsuresInitializedFields.java | 2 +- .../common/value/qual/EnsuresMinLenIf.java | 2 +- .../dataflow/qual/AssertMethod.java | 10 +++---- .../framework/qual/DefaultQualifier.java | 4 +-- .../framework/qual/EnsuresQualifier.java | 2 +- .../framework/qual/EnsuresQualifierIf.java | 2 +- .../framework/qual/HasQualifierParameter.java | 19 +++++++----- .../framework/qual/InheritedAnnotation.java | 9 ++++-- .../framework/qual/InvisibleQualifier.java | 20 +++++++++++-- 31 files changed, 84 insertions(+), 106 deletions(-) rename src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/{EnsuresCalledMethodsVarArgs.java => EnsuresCalledMethodsVarargs.java} (91%) delete mode 100644 src/java.base/share/classes/org/checkerframework/checker/optional/qual/OptionalBottom.java delete mode 100644 src/java.base/share/classes/org/checkerframework/checker/signature/qual/BinaryNameWithoutPackage.java diff --git a/README.md b/README.md index 820e18068d3..dc61c9f42da 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ cp -p $CHECKERFRAMEWORK/checker-qual/build/libs/checker-qual-*-sources.jar check unzip ../../../../checker-qual.jar -x 'META-INF*' && \ rm -f org/checkerframework/checker/signedness/SignednessUtilExtra.java && \ chmod -R u+w org/checkerframework) && \ -jar tf checker-qual.jar | grep '\.java$' | sed 's/\/[^/]*\.java/;/' | sed 's/\//./g' | sed 's/^/ exports /' | sort | uniq +jar tf checker-qual.jar | grep '\.java$' | sed 's/\/[^/]*\.java/;/' | sed 's/\//./g' | sed 's/^/ exports /' | sort -u ``` The result of the command will be a list of export lines. Replace the existing export lines present in diff --git a/checker-qual.jar b/checker-qual.jar index 63d8d7a22cd327018cc9c0fcd29a64e835e6ecee..95fc72c684b807b5eafb8e575f647f3022ba5374 100644 GIT binary patch literal 272438 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

      kDBVCe}G}jGLRl&)C?iZ+d# zqj3v67@KV4@3{XEx*Lg&*K{`rkbz=dQL{jm7mF=anqF-Th@OazXz}z(Eu8$ZkLIyZL-k~%X zdrIyZ*kfr0w@Kb?*nDZF6k_Cv_EZ8&w;)2X?t>k2GCZ-A3D-hDCrfkV8Gr>_lt`_nSo-^g44_4a4(M(UT{eZL)_3BYEnJQoT={Cy&tOcx5@B zU{4CGumlTyu!jy&Xnv^8tF7M)la5?cyvVo~8K!nKBp06As>2sb{(#H-ksji@fIf0Z zlPa|%gODkUi&yooDYdif{Jt7+vTnwsNjh>zkxFL^G4w*zbw(4M-@GO1wR=`>BDk7X zyyZ8dU9a!_9d^aBR0)!2TTzm|4r|K}w(C!8u>dLb-xrAD{HJ`{5Fk%uYx6G)I{)#v zr2orr0i(3~j^;N1^LA3Izj}!MzuOn8hO!6U4zNHt06X|U&ielGr~LhMem_ZC-`&7i z%2?m>k6GVD0Hyagk%bdg*xT(CH^;$3=E4%@Agr_k=R`-$N|AY$>8d(>+MY+iWKvw^ zEM*Z8VQ?y&ZP&UBg{2lUMmt&^k$U`>FHN^AiyC4xO(HN>D4c~0+mw2a@g!wu5qFm` zY!p~VycX769({|N#DbE`iuR6Z%|sIvP4CF}W6Tow2i=&#jHv zR}X6;6$+mpZ&3LeU>$&irx(2+sr9A7ltQ+C{kqN}J!2RT!QpI(x^avCETBq&kJJH} zDfeadKzu?+{%G)q5P?T2v>5ERI?~Ef+j%~_>mya&lp$vqn~gz6ZZ;9@BMpIGEQ*|F zS;gkQZTCFK)k;;5-Qjm7=BJr7;I9=gT8aMXDCKfHe{rI-k;QqF0QuaF-Yz~+{+1Cn zmuCX)=IDkPjtGn|3gLx?li`zCFk>h-ogZgPo`zOF@M7iu@I)jI0W{I{wP}KaNj%yk z)%rsxJO+*v{YICH@kn4Cj8J(s_Dk%~peXZFOqy?mgR2mSFlVtqcI1bQ@zNk?t= zJUz0nk*)k)qL$jfN;vM*6-&vmOFMY5*;q*Q>zi_K{Gw4fqJF$HopxhZE(6$1w=iKZ zDXyNpUg8T+ifN)%cU{}>a!`_`h} zmy!eIs!bd_(6`0=H*liU_!ZcK`SB83U?)9h?f%7wOLyV#EQh)X!Pt~8+7zltD6Zq* zE-cm~T8M%weC2Q$zFKM^l4V@h5U`LtxDK;aP9D1{ZGAm1+vQFlwVNvbNz8i8d{Rm6 z+A2)o-&K_ASr8+2TGjmd2VO+wR9&N8ZTiI(D`=M$-KM2a_Y-oH_p~OhvmY$TpwXd( zV}FzL5wNSeUA-Z2zGdf`p&hmWQOmO%i&3A#ZWRa(CP=47lK>G44E6qjoh_=bfRMIf%E{EoN$z%^K^L^p!J1U9t6%Ma)u94~|}hR(~l%T4

      U%sBOaJb1FG-PDRZj)w>^ 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�|w(?-bPvwd#I=$~;K5gF@JB?1qA1nhj1qP9K(BpDY_wZ-toK z207zs7>6TsWl7DJqZj+NTCysw@LgF8QDp5%9?oUijVby$x76p#Zaivv9UJ?Q`xEd8 zb|34}3u*+eAb-OBNFxywkk-*?4RgIRz(?6e1!^(S8%(Z$M4P&oNf(UvC)2PL%A>5@i^Re234Kz`pO(h4 z$j~SOI@p6Av6oh!o+1PQ8~}l5ju`G+x^=m+e~lD_RHJHlnp|gF(DbT@x`ea~GB0T& z9DNfXjLo-M2q?^qv-Lu`s$Gf=-Z6RZ&e8-nn+n&~taV*20%5!RXc-+%4MfB}qm%rP zFvn{GN}nA#q3ZI-Sl?g$xY)DAeg4JAc7Zax82(Y8VExaNjz6ksf4W)VptdaV5Np@H zs??4EiGuf=6qfohJYc~2lz=^Us&L$F*%E=W~R<4Tiy)AEo zg@}bT?``UQ$F*gdRyG$kn;BKS4SKpC5+{8o;$=8)A_RbJRs)m4j0_>G+`ir~IY33n zsS5oW^hMr`F1c2)D)9+;PC-u4sc1M+9Z@pnaPX_q5vCFxHi8&_dERn4z+ z*vnCLxBYSjH#IlvO;DZnA&Gz^mkyA2h8D|{jWbl78B(GJJ9Y%v6}lz^GbSi%I8US* zvF$P%4o~&|jaAMRMZFquDZ^b@KxwrcwFCr9Gy;A%9`5+8y`^nlCN1d7%qr|1f^aJj z_rQGj)Y(0g<*kV06D_d?-s#h&g3RIls2QGa*b(qd{Q2Jf$etTYkCb&Wu%HoEvSf>q zF}))@1yEU9{=9@CB;t4;Pf-re1{!x@?G+v_gW2-~P51Bhtvqt+{hw9y1YlX|!+$O| zX>%ZH>L2w6g`ZgmTIZoEcNr$Xw#|i-a{fAAY%tl;B?7xde5 z6~V6MMOTxJj55YeeGxrv(r>i;T=qpm(u9j=!q!dAqNnmKBpbL&^Az#z&2+uE=kgTH zN&JRZy+qg#R@b5l&`MGlI|?HBG+c|0gsp|W?7Yw9R{BX3G53Ag?cpG@-`LZH8T_my zXJnz81A9~6N`lYiIq&hjf*il?oA(eRBOj@Prifxj*Lx#!B=p)8@9{wor|aFYBR)@- z=`9EfXeo(1MU^2k`=CTRKFQSfRnSDdmjWzX$>qC&WMx@9Ygqp|^>sl?adbE;&aP

      f*j6&K4^+0g|Lnct6Y#BPP}EaR$G`R1lCr%#C0 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

      SY2b4K3tW^?@|!ec!Y zCr9Tm$H(JUOYZj7SSyx&kzh?vS&70$3h|Ji&YUGGF!s>&i<^diFK-cTHMpOign$%- zUY#vxGf+c|hudQAdO+vGTzFaDqpK3yU={OgjgKl80N7(7HyA!2UO~|GShPOF>$wpx zDZd$0HAW{qECpy~fj<=I!_UJzZ2T%|b~AHC(D%viUQ@=R`=!xUm|ImW+5tyPl%_m( zQLZf)_W0hM?aJsth)AUL53T5}?ZUi(>PScIW+@0iofVaWd*dxC#G0~oa6jXox`p(! z04`V#_o(jZc&3jzEuo2@eC@K6V)7FqKR#4?h*Yp;%gucUFM&=BdMW9WU(l+5_lKei0_&*NRhrTWnxz#4fFFhl(tBH{0aM#f&$%;Zni1VyXg z&~Jd8wOv612}%8NFg*bNwjNi_wfRD05Ftl%v#e|&QA$O|MDpPkr%xsgV}!4t=iydx zc+sjsq@gQLpmb6nvE-+iR|CL_!WXt2kY?*Y6!p9h+&Wan3%8L}jt_O~WQPBGdN_`}5qzE+M4F(phgWdHOF5C)9p<+XhgOSfzlHk>O?Zw0^SA%7_Eb z%*Ep;LPM;BHPoj9{i+lDJuZs^IbwwH3ONKj8aM#$fD>GWP(kppE)ba7s%pRng(o2< zUexITyWA-vY4>MO^b{V0(D0&m(S6+;GH9(~AuU>6h9_zGcR}6O78$YLV-pOdtvHT& zo@QkXIkPN?LvcN=msFaYd^U`dlh3*OYCbwKtIx#rUT?>%*Tvzv+n3(e>;4-{UFRf* z45X&A?cdYoz8jE>nlLo28R)Z7gaM7>iV5vff9Jw-QDYXp(x=ufM}Vka(|$js-9qe> z&{)BjzxNO+?(~I`PN2$Yb=oY;<{W27QfGdrMx`pjTN-7)_y&EJ|Dg3$*m6K*<%Xx9 zC*RpyWJbkuP8y7GswF=$0Bl{*k~>FkY4nLbc)aO5%>hLkrxqL38Y!Z)%sG<)FA~S+ z6_{_W;1};^LZ(F{P)bl^w^#>Glr_$hgd-H?6QJg5t&g$39ESVQ%d#tzKc7 zOtATxjEB9#*6k){+7I??T83){yHIkL9e<0(T25n6oVXqaGs3{@^rnjtUU5zHM`02X z6}EaCtfo9-M#eizlkLJ@zmaWFSDtO(o5J%ms?w4%ed_9_yJRyQLeyc z#G2p$2-Q+nxk~NW89AdrA5(ZZ@bjh`J91Fd`!?+=6r`;6tDXdlmCv==QEu}rI>}2^ zR>HkEsW_w0nD?17B8GqmV=5p!Dhc)o8{s+0FjYK?rNHBBTF(vE7qY~MVYNVP6e;f% zzu|d_tng1Zll08oU`JEE#bUogo2r)_w-V-qD;Mv5H2@BVJS~|b#ectKq-`y0t1h{n zAx)rAYT-Nm z5{_VWLl=pE_;`)K|Fs+x`$KJ}QsvZUl^OBlqI)L>IDL(6 z1RD0WrXkRuv4^ukEV<>C0TzTf(~^myG%f)j@~!(aszAGHra&vOCwACl^Ae9n$es)x zQk-_jFmxFAL^2%BI-#o^VMnv5C6Y%ej}VZQC|0 zs@SNC?Nn@A72CE^vA(yu`<~m~=ZVjhoX}1N3L}-3N zgxbRoQIe&ok`YHo=tp!=#x;)>ee}q>MqxeSE87a3QrCxPVa69KapbM^$P>Z3**4~2 z#Iqd^&f89;GwCTJSGt&Kvw9O)C3>W`WM7M&!uQ#(-vw-Stfis`ylGFee#V(`95c1s zQx=S7ar^NG954_UA^pM$p``F3BD|xJsuWB-{6FfU6=%>XzKN_zx@I5I4%S`6KV z$e;puzU9{jeBC=?>P_BKEgu0U=O1SD7=a<7R1(QyZPo^1>146S(z}W9@^!yEp)W$8 zR?fdZd-=}vPL*b&Ak-~~jphz2Mlq8oalyOzJfgAOSpyf~*KChiIjMOH*QAn+X?&h% zM!$)ni^I~mv;V!^7V_M_OxYjDs=ZZXKPAIKLu@=uij>|#078rS0II>L>7ryyC@c*+ zC7$ZqU)e_P83j|=KS21+8;TEq#Js^x1bb9gqI}CxNCc@L*}X{V2VhpyLC8 zr!{28>?=rZc|0UKe3(nKrN0yey<$@q8I_1?i`nj#2)m&xXX|Tdm`T?)Eeq{D0!5+C zcHXT(F6Z!4%WC93azJv(H*z?|1}{705{lqY-vaDix`K$5^Sgf)CX!;|?C#e9=M>aX%t<;KJjF zNw0Pw8^6vCP0vBTvryz>1=2w6e;{P=iH7$QDHc8-UT$mRmQ^?(Mg8GO_{!f>E-)=0qOmr!m7c zLt6y_3O`A=N26L=@IPj80oM=vh9!Eds1P-8qU7pRZf8V37m+!SyZu~h-y?Ted!E~2 zBNo(FVZ`moh0DiiR4HMOlkQrt0lkAZx-M6uHhY%) zTZoivZr<_Whtyu~Sy?aAUJrffqSv(uIbN-jT;ie~^VQp8rfYZ|$Ft5_nM4s2yqfo% zvr@9}H(uY?#T2nyM_`S5|7HBbRsm|a8B`^a%t09ac6k=9??|lwA zW*?m*q~NBV)aB=!extz>3QyUDJ@ws)xyQ7wqmXhedR5u9GABKs1T2)!N4DmCX}oYe zDok_L$tV5Ut_ocmgKGH^I*i?cN zNuG7O4S3L8zku13fa1|Oq4!H)N?w4(i(M}3X~vQ0Mkd2X=>0HY1w2QyPNq-CqK2wVx<@gsy&l1a{%oZZ4Xd!$PQc;;3$Yj?_ z2Mh|r3dg;-+qIE=nk0e?T3T94VPm>zR(-6eN-3wF@$PC@L>Zm{W+!3#*e4u-s zDL!V9_*v6HH)-dRH!YdMs4}pa9ne7bYJOunOlI%!V7*#r2>C;mg%97o8_1zb7sJ(- zI-@cZems$y!`kR=>2W;1VrF89sl5!>Yh&;_zUb>1P4-wVhbY_nhMakpEX>&^!k03q zZ-x0)`i|NzzMYdSW9+Mp*ewbwy_vQy>an>?RF|PIzzCv=^oiJnkkTi`HHC>tij2X8 zcM3k?X2UqW{;zO@HU6Cz!BLm4ajT2%WE>gKVq9P3FD5FR-e(vmPU;{ zcuaSKELWX^H2I*$uUXYpp}|2}T)dh3$sRdhRL+lxYDL_8MJG0|DxoFC zV4B$%|jV(`2aJx(z3vEIhvzTSU_j^fO*PgtJ+j-N(Xv#H4NYiU7& zra^XoxS$laQ4A<&k{hi?+;g~eZMuOe`|v$=;rX8QQNrkj>@b{|TngT&&Z2JI_8io= zb=c)Qjc@P#OZpR^n|0Kpdjv2aT}2=H2I%cu57qPD^JCguad+IVFIQkDOzanTVzLl> z?JpQC5<34oi~04UrY42k{Q+5O86Zm)_y<|cUqQjYK=1#(!~}})i{TKjB&d%VDr`A3 z7E;Py!rGFn;1^blghXLu(ae#SlChMrHf=9N43OGGs`#{;tu2wdDLW*iK@drQ71&n5 ze6Efr)gWl;UT~4vmnatGNXI-UZO@2ckV>%7bh_Hd@yV3Iud{!JAHKdjWr5G2B2=TP z6ZWnoQeN%XB0^_P$uNzM`Ho9VON0tUl<>Ec(&r{oI(hZ@vGtXxFQBlO3lPvb_2LAz zAd!Krq&xB!!|ouxH09e_%hXYjKx*Mbb#n4l@>X#JQnAX0Z6O)PSTY|A9l<_9rG)y_ zu<^A@Qm}Pw5_SeBQ|(<(B$##*yiR2^Y>dDjSN39p+nhK0`^K(52>TOlTIXE>h^6^?Oth2X)qZ8 zBX*N**vPV)n^M{Ju-YvJ38Yb}^4fACG!y*dC=87nb6Y55$X)m?PV_waU(a_*5LD$C z1WyIRSB%JTChb@kyAsF3iX6V*Q2-ohGvyM&O7h)G5-eSZQouotkHb21J{z2?mdv zOmJf7M$qD8=TZP@z%Y%zB2_Pp8e@~P1B;ji1EgLQHdLKKf{K47c=V(^PJ8>OQ&~v7 zN?rI&hK!u0fwm#WhO9m?6H`Za|5_LPrbrQ$YtTDF6|C6)W>AW&YQWA5S=4ud z%jp0INYfD8xor2e>k{^?-5@)!U`Dkhaek&KLr`8hAoSwaS)AEa>}jk*YKpp%&=VXN z%&w&BHK&x^`5>W{AS39QxFdEzD)}@m4(bvugWcDPL}CO5V@L*q0Vsu;%K9h8iGI29FtX)@V38z*ic^XP1oWjtS;D~0-5Repl7kc+Z|7{_#Hl8J#oUair?OSD5}QY7EOZs!(oQdS$5cb;p- z2b_R9j-Vxim&WVmFos1XLQC>Z1G5*71Y;j|#{#)!AA6P@79bP2Hgh*U_bJyeuVyni zk>_^gYHYm~=q!0Bd}nL;-MfQpms`Hvr@ee-Zs>UtX6z=Zh|MgT$DZs zHN8`IW=bxd$w$S&Sr=IpPA8?7$> zMi&Zjd;g*fr~Xeq(8$2r+Qit##M#`=*opq*pSoUurwwQLXPG5snOR|v#5(yi(lrNcWX>3u*;eIGB>t*m8pTR zHHD@(zx829+Zc{6W3Sj{MS9pp<32F8g7TG)Cp!z=^ujT z9Yvghy_WEK*mh?nUa*UWXHF~-dIamnTZCtdx%1j>^tG&M=>640mulZwlLI_7FaS#s z{QrBzza_Xyf2g6HP@^69!{J~`*fk(h$iU8mvsHY@3D1Qvw;-)frbx;?#R_=ik&5&E z2}ItGuxn`cg$pN{X0-|=CpHYd5CgEc6~EU+y}K`eDVS`6u~$4zRN9us@?#*n_ogNm z%D0O4hLH>@22z2d(4DZ&;tK~9>Zuftp0##vF7I-CwT*%?_o|*P+&5`?T(38dC5xh> zD_+CVV`-lpo*0gilm}tz1cR1$`b?E}RpuKb={K0l3Y?|@4H)SUZ&akJs5y3TJmy|F zMyjO)QW=qI**IJzzdBc`y?x502^l`TPLTeRI^p=tia1e3uq!Q(vYCN-yWHY!gWWA3 zxc3EIiL4@L2j6J@nfP-3`pAhPP3}3`ZhFmXyyF|Xw~lmHmg)@9i;B)F{l&qIev37v zSEO0x)F5<;+lZ%3&!$rj#RZMnc0OpbL3_DO))xbPoTYg~sR|Nu=6xI2!APaBoo?1iX;k}HRW8}5`@vH6D#$%;a%yFd(?e$ zfvyNes*j!a{sz%RunNDiGxacGs(~VZ8I#St<(f!wNh_DUYukaP#>7hBr+>oi$tzN8 z(fN@+Say&>UaV-UnWbCEDhCk9Ch3n{(I2fWV0E~;uM_b>UR5`ib}+ojxY{t^f;2l; zE^yH+_8ANb0mA9|#uzch081t$1pRU00I;!Yzid#tnR}=1m@tP&smA~meniE#OOEEK z`;i%~5+$|=uX@R>QwnN2u>)?{Fe=UzW<0oJh@sTPbt^z?=e&ac{-AIK7&HmuS+-cn z?`@LH6XFts!Eq(X1xFaW1WbWCqC1(tC$06z@Wb{CL1;P_7(DLL7xaUK2{kjZ$u(>p zopo8;bJ2vdG?w7@^3ZOd8PbP`rbC8t1uNjADSw%kW~@M7yg`YFB&!+y#JNPMfKa7= zs_v$&7YAT?ApY-&1S4V5l8_6ADtx`bH{k=K({V7$hN4UKOn6)wiEEOC36G<9xLtXo zc*hqCR&7R_MT+|{*fwx*;)gsY-Z@t5sChHKU!X;Ql#30?s^yzmQGY-ts!YfgQp0;C z9BKa6+wsF-P3@COsN~j&YD-4sy|?DBt2itdkWhYQ=OUJ^TF>SMxj(H$qo_li@B7pz zTP79@tC?8U;@Dk55DZAAeR{wIE-{hEcB_Td#xb#7v4a@*V9X=^U@Oz9S(yke)6{rA z&goqID%aulzS0WW8A>wLkNEs*4=;8L)I}I^Kgah1Ew_&jLGb_8|>De%{n2{}G z#x>eJeE8hPh5Jm@cHr>3vVo0c^<9rz<+Do_+~4U}$_zr?NdYgB8SoM%{|_%w5isd) z0T@61%TxR<^BE`HD*>Vh(IaHF6A{xX^J5zT|p`vyx{mX&JM5)l@Ttl8ciouKsiML<7FDH z`ZuPyAZZATZ^QWzb|jThC}2Bf=sThu%T>dreP2HgsuM9;r@pg|%kwgSH9Cv3XNoAP5373|C72_=xLal><=A zHYEcr2ycwPgREVsWB7f!CXsU>-}Up$Tt&5hfGflWj=|T=PAUAutQQCv_g zluX~Ht)lQ$NIzGiP%lP@=98U%{nzraHWT_~6vxpl-=!o86#!4ou4D zCC`}i9nDxJHk)6BR26~iD>B}>qRGIc4n*UCCbXJzw63h0tZh9e)3UD87)vp-#jE0y zGg;_&HW(RsE4K!sVNy5N#hR5X_|FUM5F#1Jgo&Q15g**mCL89W1=OF5U-es^rIwoJ zGqvnm>)~i+OMOG09eL8Xh{10!1lC&@K&l{FyZ@A({R)dRv;`b;fXqw|Faoape|U`l zQ&^O<6>&E*v3Itx`>_|x$q+?cTDSNBz z_JEb0jh$f7^#+%bmtOonL^}~m&H7avH`C3ie3f&zDNbDq=}~$Sv~A&+J@0}sz#NDo z8R>-M`95du@CIoDdPejRv<=Qne=<#+^cYfMqU$K+_jox@TBiz}2|C@R*5vfQfs=qv zx`!_4ahx;&*+1OvRwG-u&y-^R$wKhp=x9@!$sN(0H?ea(Hp_vi{)1XQmaw(G_o}~9 zlR}Dk$`0CUI>*Zgg2h=$~h%F?2Rnj^8<2%8?XW)Gx3k6VYma_Hbahjb}4 z94{~z(Xt!2Cw*H^Zxv#a;f?`GP*Svv1b()yM)o}J{v;CmJ7=)D-G{pvJ`n^@&}mda zphN^TbKw=GAs|!+Uw7Bm!N|O^khIh`u+RieAe6-?WJwz~n`fd!9K)#KK{~q`yHCwl z3q_@ij~~-%gIPnrhb4=FXHxXcgK{YgHVf*Ce1!xzjqI z&IeDJjsunU!A<$JoNWfiY`O$OP)u!&dNg_cn)CRz`tHs88(|^`4k#;67zb}jICJsm z;*X+R7%s4!z5D`eU(xi)8W(o-F8FS9d{|pLy>R%vaicEqS=+~}493p2mMJ7iYv(s2 zelD&Nj_huotUc`CVVT^?Ym=iLO$KtC9CeTON)>(F^gu*lu2aRzPn{6&waJ9)4`S)Q zBDQkSm?H<89%ALFDv21wlv*dB03(j1sDfI-55CE{nm^)U`tm&t(G@o=eq)>#Ha1~C z82L-5>3&E~@L;{;>0??r_`~BNjO)sU-)Hh5+l!u$%mkTjUuy5o_~2wW;Ca)D9h^>O z%ez+ZuRtu23kyatGz8`HheZ01`~#WFgD4qMXLY^Q13jHVu1I|EK_DAw%oiUALh93tS;@nyNtS(KEc8)Rno9Tim&;d(}FPl+!@81(d7f)EkZH%sq&|UMFrIKZsyl1@>KHu zt#u`@U5BE=p43ppf2eUDN$v|r#ELFYCEVDesL5Sd>H3S^P~MRpyr}d(r5Vhr28jr97y|CkKZ}R&uxUX3nLf{UXF0GKbZZ ziO7Q%d>CL1{x%9r_UeFw5ydeb1}JYC=&)#?nX0gS3CP?vGR0us9;1`_d?zcn0R?FH zk?h(jsZ;!ss?KM{+RyohB52;^_DDr2^TAp;CUl2IA)-BaJ+9Cam7T4ijRdg4H&~fs zlBGCg;a!-QtssVis>hlf48-@{w(SDQF=UCDQfDiI2Mb~dFK0RCc6UF9caT_GVX|6q z*3JT*8|hcE!Jgwbs{>O`ctfMp;5UrGBU@LUT(7Z!+WB+m~x4ySmlQ|7aOCRHh3-0mjrOg;mmXq0Q6}2*K@T)-;^xNOKO#!Jh`Xd0$+W{o^^8b%=2~`6} z14lEb-_rX6C7GCI00-28T4aMFC`5|XoKT5sIfbHEws`D$!ErZx!e)Q9k{<|R;`@3v zGTL&luBSu!Rhoz0x-=GDbekYUgW>k)?a+q0wt#Lg>+nF{ehpvNE!zvh+IJV4w_!(aNfI)w;;q$_vXMs-BVp3zjX612? zDGGnv%MP4YrKZSlWehZRax2P5$+GO9CJ2}LiS-NgBzTK312zVj%A-Jwz()Wtyj6@E zI6brh6r%(4`Dgh+saO6y(#2dJJp~VN)AxX$4V*BP>LsA9RyD7RyKX!wqbplg{VDJ= z+-I?En{x%IwH&>wfNo^U>Uni`iGm8MdvSJj@xdeh!2Ba6O#+?jOB$`8KbTrpZLqZ} zuPf8&m6~E`**4rB?*$BcyShZ#TDrSoT4KM$OHy08sGUy@nK zQh!^0waRdRsSIU$0%lOw{;B(F)~{?OdN8h~Ih552kp~<-a8v%{&-LT4l+}Wqj=l=u z?Mh)ke31Bmbj^OhU#ePw2_+QY`$~5E&)ooE5&H`-v(^^Dm^{4GYQgyo15Bi_ls1JT zDP`-It@jQmamfy838stwc=OB^w+^Qg^`|~ZxaD05&C8!*X$1zPdR8~HI3$z_@n)oM z!Q5PN4O#vJ)TL|%7z||oBw$b*V{Ob)!S4fT9e^$!{Y1*denj2hix+Y3J}m<#z39YX^V*E&~a$RVI_y^ zHqF(sjG$J6$dWefuX&S^jf9CV(gosr7p@F&Xbz!p-2{hK!4)Q8_cx%4(u9nT$S#Z` z;SCAOW;kSSBlCwB-^pKSklxq~*3P>w29#=0Yd=^KlIDXMZB;S11l1(VDkIq)O4>__ zPD;21d??GHyGo+6W|F={(|IZJbc^^L27{UqSCFh&89ZX7Y`5a|r8DpA1>O3K``X^K ze!ub9mf4}6_Xd8wM$bhJAIWg3Zy(g>Bs9!e+Ehia}GPd-_dzKSeu&z<^`CF&P&N2kq6c^9OWaogrZqhs%Ql5LMGyIa<$zp>BUV zR#I8f;4-6!>vyPvXt_VwR}mSTitPp!AzDJWU8D32$-jl8)ai?yb6=A=V1&&KwaW|J zz{cIR*NJL7Wf{ZtAW&vhnRDkcZsMAL6BE^fgEA8I!iJxfxXcu*jPd)TCk$b(>xy#m zK7*NtJ!f6kv2$8wh+xjR4LwlAy7RzXom$n8^0_(Mwg5?h|Bd9*pO~zVh$gpYc2-6` zjKu})z0v24;}W_cOLFV-IppoUn6(WY_ZAVytAU*?+3E1wu*Li8qPgWc^*X%k@}B6_ z?+h8y6HPmavn9Mjmt~CHJg^wfw)fL9);-xoWPJBmQ*QmP!LxBQ^To8FX0}ByJzJT7^mB-hj{@#O?{uhG~!)FB^_lC3vR!%SzdO=>qMfK76g0<}K2Jp=TOafD7 z#m??1f1_Gp7{P@Vb)46afeW?+c<#I+$aiP^JoM{7W|aqi}NhlHRub(e|PO z^okvoK^!DnbR*`fGzbgDH4~2M>L&r*qPZ?_ph2y7W6pM32mk*~MU@~%zBo4D?#Vn5<(~6;!o)BE&V#aa-ADe)$h;QYF zH)s*tge7-MBx0g5rPoiT|;y_vy-P z@z(@63Lp_+{0H9={q?VYbH!1L0=B<|a&AxqcZsm!Za(N4GegA+Y4)l@0W!~$q)|;k z<{7?&@#ZB#S{<0r;7M$1+RRnE62C0pUsVxrIcC{g;XHde-!jHUAjRrK{Qgr}E_hPL zDr3;jlSm_>gap%w$HOM7t-921(Vec)%td2NA^Ad+mtMOHzUA^sZfSL1^K3lA$r1HA zZ$E2XuJTZm?l}p*_KhO&{p3nrKN6FQ^|Ve<0$Wr%bZzoOweZ(e+?P~t=aA%WKi(m| zrY=kH0LagMYy5T@cikWA1kAjO*jeQp^yS$EEN~xEQXBRm?~XnfHC7uq<_w|!(0z`W z0x}MtaFz)7Q(SY}Bwwtk*EF(v<{V}CN#T4@ukaQTA`8YzHQi{ACl|(S93Y?#r{-`w zu*3Qm3ktHK8z=8WJ3S*3`m?EEccx=^d&|q$Eh|d+sU_X`eM`{z%_@_Jm!=l7Bl~8_ z&^2psX&b>ZMoSXxx!I3OJUB`xsey-i7=?FmTz?WJv+hHe8wrM=18EYfUZjkhPod> z+W`I{&xYz{m7R{5Te_?+rniNw4#{bjUGK1&ICZ){R490M>A`xuL)yUVQ0%b!E&GO7 z?{x+(O>wxlN#pa_)NN+OuF#xfZQT;5-wD;t%M1evbN-R;(aXGddHHo&t8r!H_d}dU zOhu|m-Vj|MpX>eAB4~kiVG9|MZyR{%D5t0-E6;sP;ct2WS$z0QO6(4xyUQNt(j^ z?9){dx6kYS$$ssZdcCx>F-;^##G^wDpekF-CmuQuqWWT~`J$UgwmJ6@V{)()XDj9yqneL#Leeo?K z?Y^jq1-9Wk{Rt$%L5KkkLhzqndm%d;djlsYVL;Qu=ua2_zYZn1 zz*cZJ^lzSA(fz#cN|u9g8vtkT_N*2;kdQ)uMVu z^bWxITm~O!HOw+Ao`#HpHbMDZG)wq?=d?_2#KyPvq5JsG9t{~~(UH)SifLldnjsak zorue+!_*8?QON=2ES~FDq{plMoGyM5%5=QXcz#=2z}bRycI!7Ku8%_6v3ni^!vMhIvw%!r_#aqYz|C2}+TPsYm(hRI*|IfLbg}*e&`4N|1{9FN7dI%x zXRz7x&mX)J62~N|UC>bk=X7(rrIFa8GnU7Rg52+y{e#~G&rh$|2F;MN&^)3@{Q<*s zs8^}d230xVS#Q1kQS)2AydKK)3dfmi+TeH(vKb?(49ioVO+tQO%-h!y8kySPqWUTc zrQTt6#Q81m20-!Fx33A+(F%89F6n5tpOv7eYGB!LI6v-{f$IDAJWLV*=`Bdjo^4GH zQqi7>DqD;sO+GA`BU4-v48>B$)e9+aqc1dX)Q$)*ZbQQkJ47vD2Vx~*iOk83MdtvP zWHS}J&6S-?a86?#T$ates2Z@MtIYg{u8E;Rv^c0({KU>-iz^k-do)ad>uDCnin7bL zD=*Gv>Wh5mfbbx9u=dj_)tIeBgtdK`o9>#Bvux?>&%0nBBrDNHV6`1A(l2W?hWR6{eMNrI>^wYvx8r&}~3v{ChBo z(`eQ?sI3drbHy~g6QUft1|eZafjj!)^G+R4q|ZQB7wW*aM9pb@q#IoM>><|~jE ztK;uNc|G)ojIj?o$(iH3e_93lg)y?%%ESE{qW#6>{ZHQFZ$V$#!r9tH(#6Ty!t@uk z_^-epzaa;h&>GyhSJU2xMxyomK%X{w1VMz^-$$-E0DJ7~?3y76@!r~4qCdN-n|k-u zd~y#^)fNrYCN{4%odU}Pk+C-ZVz*492ZUy%YjRo;Z?WN^tZHtwrO_doJmNiOoM}b< zeVPONxOjx2vFSK#&pn)l%oQ{fT&S*Zs)Cett|Z*`z<_WJ>n!fE_GYHyJaw$Jfb={3 zr`wGaSKPxMVyrTv6vd9*#7R5BT1nc01VcBl^vGk^S*uxDmOfHO*q0={0*l@*;9uM}>5s={#>6 zox=tW+gRxa=`y@YKBTX1GgnFPGcz`sOMAU~z;{R^u#4zlBIcZC?qtH8G>IX*_%4P8 z--JP&KNjrxx);^Ho9dHg7J7fmx}ttS&G5`|n>adw1E|m`3|1CE>QqrAnRpzb%*C$* zsl_26|9~)1b=z>}DU~cUbkzI~eg}T=w{ju9Zndk-!+2vzWVtp}QHuxYGOCrm7t3u66s-24P5$dS?^eZ=dGCWW-&AYA{2Y z6q`~3Rh?6NBeP$G!&6<+iW@#Xj~IvNm7GSk8Rgc)zDFj!qPOkjGi`?tT6=jUOH7*B}fg3SYEYUL(1YZ zCk;lQXaR|4cC|i}%AOU&s=jV-L>ycg*;!_{_=1$*+y>b=us~`sQwc4?M;gvzW^O58 z?}e&ipatKVPw28KPXs6p=gDG9p!CCN-czDSwDWAVJ@h40O;`hrVoi31S?0`lc6X+0 z8wUjY1Q0Q2usszD?FqKkkK3P8xP{dO7D47#+AWx*d&8#)tRq)2*Vhr3?4T}AU>NiA~qCIb>eAv@QT~{ZT)E64n_yGMRQ7p zFwxnyb}RS$uuj6*Im^SJSj2vLhwnl^}kmJ zGQYM#g8}ZCl+^;{9H>PCh*&*QRH8*+MP`iT8@sDLt|R~pN^c-R%?@2V981f(m?My+ zh{e)kxC+P>PSYy3H?n@Dt-^6ps%`|E4MNbE8{m9`y68eV4Dg>H@J|q})gn%Xs_#7* z&W@qBwpnTzFfa-jfA+qW)3Q!PSpg89H1IEYypdd#C8rjQjXdfdG#}uH5atlduqmS7 z4~)p=;TAV1y#?+7ZP?;YS)A19sruiY9QG4VmMLYe3xp+l1+U|v^6`)<;FE=Mc5Q-F zNuk9o^+v{sJMTidngIlMDEEJejL;v^vt*LZU{1K#+}Gmj+i$k8;vet}c6;&=xzt{h zTadiUv4Z=5B%J*Bw3NK8Sn*diCIT?Mz&|y;vWdI%zZ?DE$}wbPq>$>;F}QRxdM7FK zv_u*c>6!J6#Avi`Wrted_qVeNmLXure1L$*uRU8+G%9WkEpKQVp*7{x@BWUWp{15a zxIV#d`lN^HzpSn#S_@8`2C({?_3WUOwavErPSYoW1D}qkB3jmh_(6x-4{3QPJZi%s zr3I!IwJvY-D*KPW1;LrX>E^jGT`G@9j^ zppq0CgU+njmZc{iX2myzH2=P`(Vxy_f6FzFX-4TF0H(%+_~*HXowc2#lD)wn1f5B9 zzqK;JHobiN#R19Wt>kOPT|5G?NHDErjmiu(qbaa%Ji80duURF|uAWl-p$?H9vu%f1 z52+DVXMcj-fGW}&)Dh)r95%s_Y})sXQ4NORV%zCIegHZYjq63& ztrD4)uCcolck!Yl>A^wW)0iV`S*B?kqkdcQLMBhpf8u#GkQ8$^l|HGblzB;^kGiV- zP6-RHqr?f(-Z$$T-GMoyU@ZCSaNXaNI=%2l!CY@gbE*aXJl@mMScOk>DhB;L+~bMX z01#}4Ua76}4?auN;7e6CRg?KKbxC+B*jrZ8&IdF4mQ|NQ(qTt7vGAIRJ|iW)TQ?~H zC^w6}T{J^@bqGOPfZwWfTQ6|#krJZ4qATX{2}OGbL)_WnmZQC-%jeHUtmAu&d?N$k zUQ{yNbJ*av306}fJAb*&v)MwOW9{F_bc_O5+9_`x9?sZkIaCQEz%KR3i zbvy}p&QO3L{2!ND{vL!?Y=4#hfF#Sr`1fHr#T83{UVzVn8qCjr*0HCL+TqefNqu1Ch#svkhP( z;x*;%=59wckx|{BzlL%t<04EAd^}7>~d__jUTQH%0uxv=diVr0y;wH*Soe#WFi2{>)sd z{!kCAAH4(P13aJRaXpktg@A9Mb~a|&v-<v>RZSe70lE19F635I zM8%_osj#pl=x;A}yHKdiweB#JmOPX!Myjw4Y6V5>i8Q7v(3bTZ>PPwdSsEMF@eR%io_BT_NLY)OxE6Qell%`Xjnfww+dj2t zVuPc52rB+}20yni$IFcVE8;qbXW=E7yOV}_wryflNTIjYi+LP=>)L#%=ylA<;tg-laOz^9jfUjjiMWUT<~?)tdlC@S{J^^K*zx^mb4 z7Z{YO@CyurJ&!8m169qn#lBk(NJS*Vwn{IezXX%^ufQ<3;dZxRZe_}~k@xaWjdIjB z2tfsp*wO#OYrl0XN5di+-pj82xoi@Cv~rBTvV!Hu%6E7THIqZWC?i3m)Qf@&$Fh7m zft`_IgzS6x894Fr!n6prkDN_YWiejs=>T23Uucl$3blckWc&|W3C5oh9V{kGPdQC` z*N_rVnp0OlY&5REU5{}dEc^^f9j|?iN9X1W26UI}4s%fl7<2R+(-2l{d-<5-2t%m_ zHaGf@u7ubB<{Aqy;;QulcBcW9p#QMU7qtfH-5Ge;xj6scT8N(jtOmghT=)QN{lR7n zsHx7-pAhwnB*$rxv_osT#dN_Df?(V8^p)MRe7%A)<8Bzic6R-_qa+^YYf&?sD z-3(bLh`MAc-J)2O<3X%T44?G2)YRUSa8NE#ui%CrB(`u(-=T2_L5cc%#z)nWE~I%h8 zn9AJEi0955kRCfBS$`10;!>IsJ5Kwb)-Ha74vxTtoB`)n2spR@sI>6+kfv;B|J#uz zDgGv5>~la(b_C6G_5{@NxrvO70wm`vdCjyyN!PTCg;D7Hx(@xMxz+K?=_!Yk>ArM- zJc|~QeKpB2R02!5auslAlX?~sNq-I9kl5I@zk#txe{hi7-LUxh2&sX|FlhoN{ctF` zi+@31W48*qteGAEAxZL;My zU2&G&uj_rBKM$^rH_rE2E8-(q-HE7MpV~8lcp%gu;?=s8VyUE;umoDe4dFr7$jcdT zQHCw0P(*6W^K@5-QOcDC?HfD826y-(U3f|vH*pxl*VxL>@nFhshq#?0K&EKYrH|ST za7EeD@b3kB)UpPq(s{c?<{LkHNeW?|YTCB4)^eAZ~Z{6^aF`f3Sq#r zJEx|633KDGC|jteGWM@RLki&b{xJe1Vr^mrX!`uS)BCpq5455Wpmw+lT4rfU)=g3! zcp|T&auF>g81N9bs1AU@GY`_RjDa{5jhx7`6wu6>pi%LnXn8@Cb8M;Zmie0rgjMRR zqdU5=tB{<>`K@-kDD##w;$(uCw`L5de=9bWck2FBY!q4iDmJjWJL6+iq{gOAFJ3Cr zMsFs1V<%$^#R_gRjf|4~TAcyPWD5Ar*a?8vPlT?I_D$i%3@VCvv)Z9e(Zdl(*nm{L zc{X&1Lyhq>!TEx>Xf7NTyI(U6a?Ga<8zo;Ezv3%Kjf&>Y;rb^#Kwy*@q=X2moFP;p zIJ~GSnd%KL7NM4r6rWVCC7EgB_Scm3~@_?jAcR4)R-WUv0r+p#w#fgQWaxm z-yQd-JofmhZJ%~ZsJ<7jskTV5+-O!tmYd3gu_|5N)NxSZyKJkC0CwgN!3cQ}moZ?$ z68=hry2&sN2P3GEE(0@iq6jNOY{l~6xSCi?3*ID^-5NdoyS~Ko(q+(XKYJtokoL!K zj}=VV)p1Pi9MubMy2TSX_xq7vi@dm8m2N70heuqI90@B~&B&E1IwZJeXIWzD*P}3) zSoLH0G4~9+pMY5q-8qG&T?cC>&>Bw@&Qkec#M>SdqsZz^mcScX+|ZNBPsa-0yhZUh z)n?B;+96G5SJGAizw4F6O5lJ*(nX=Arbpk$tqMlW6~rSLEyXY9ax)>MqO4lc();V7 z0?zSYJ^KIHV0W@Gvo$fcHF5gu8tyNz`seS^{-?|Fr|Y?BrHNy^^g6lcXE7$8)J4eYNA zSLCA=Woqi?+PM2m>lN^}e`&oQB%?o=o;rdvkUK>&MU7W?qND09aF zRY3`veyVq9EybCB*AV=+GeyR`BE7?B`#JGIpy|Dh;It#>{)k>Zo+m%>`A`m_q48)A zJZotBfIZcC=MbeM`^v@92fsj}=DcoA$LqGpsQQo+56%|+$e7(TGJbfB!mEiZ*srFB zeZ3m%`FzRKrL}00{b-MxF{jB%n6iwr-(Ox)m+N5r@`dfp^w{MR?yuL;*%Qi}8sO0- z0ptn)5%m50HTwPJe=juw5?uh$*XLd>auz*&bqriM?z29YascI`;x!8G-D1;X>-jlW zko;S_k&tzdOb)ktZwgbb6Gy_0{;&~9i6I&dgL-Z_%7i`b-1SF&&M?p~!1bnn(3$I6 zs_}b@m=C>b=>^(-k9uEUs!J>pF!@heRU5|S3IUcBnTJ1Asuouh%~VHWqeh}^!>Nj%sS&rv z1Ud%dU>=I9{Yd90oRoPqLaVS6T^4M$Cc*6dtF|rtW6c?m_KjnOl`G7x2<>6H;yxKV z3Xx#PL%@ibD5i}_%s@9WFvtzjQ{kta2pc_q7L+WI_@FYpM~xMwQ)5Xb0IiX~l`_Zy z5lQJ7Ob~7@n_84^vOM0g(O5VZ32lke!J>9$Bp09o+r0yqi{qwR!~t2R^rOy&M4k0^ zaQ$-W(bmQF*xCkOHprtA`Cu%IgEc)n;k@qo)P4MChM`qPT|0hULDi5vB2FWc6zr5#o^^xSUA%) zaFUVZGk+GH2JO>$)D0hLDcj!2)O0k*cMfNP#8iG4;6-}i)Wxnffv4>VuQG;(&hFel>S|$=S#dPt_=((|r**43z4BRTmNYf(g$&5KHTs|LX%(vHkO3{&<4rapP}jN8g!egukx#mMuOZ z>NXcO9a;J39bq{G(&+8-d>xn91<)>C9HmHLQ(|uhGKeEl`Xa92u{Ghur4>z$9qd70z&m;y< z2VBW<#NkTPx)?`;M>pg>3v08#$N9YxsxIAWk%T)!$tEJ#Y<7eA#{m%d`Vl0 z#fpnDpGD=+3q@|~0ZRatF-`y;TZVw9J+>qK9Z$jgGIc2PuF~mnu-bjhRR6MX4tk~K zf$|B7wDOz-Wb-O|TlNfe!Du1wDJJ(`EOd{LMUTE=?znZc>WhQ zvf!|el^Z}s-EkSp%3JTn?1^SJYuONTN$IH3!B(SBpY22RS@ZNAB+sK#De=p3dIQtR zUooZfj?Nb6AGdu_GqqVbd1`A0KGMgBUQ>VR@?G5FNnfMTh{JDo``No)rK**GYxzW@ zz+!HbB{nTXygr`pW3WMjn;}h%uD5&O!1m6^0f74ig2SkK<31)UtvWjHIn6fbH^cWWy}gI((S198RSw8VJinWf-ncLS6`P_J-&$+fj$0~PhedKogm*&e zSrG79)h&7^@-BB@Zr5{G-goH1NU1fb!|M$xS19_5x8QgCoVPG&{bzc0z3{zk*=S)df(GqXfg^j~Je$^hb)yj(*+P!g-g^ zwr&}~A#Bgbw2M@~{{JxPE+Ybt4YL4__3V8NM1TptH6tXt08`)y4b)nM|I zsZCAV1g%0PmfJmSJ_NIyNp6EW)K;yM{!$nLT_Gi)0W#4nAP@-ruE+oM_Mhdh>wi{P zblz44yvHlmixr274j+M(Rb*|H&+Spq&nF6}$u*FZzmF}#@Dx`jTNdYGBH z_N_w4!-%5)J*kt+5O0&lsEY+7jlsOQ2F@^Pye*r;ev&D-TCYA+y`|w>vH1FI zkNFKTi4&+@IV9d-N)Ek2eFk(YKzY4sfea!M@a59^Z!npUkU2+T`#Ymc+UUR}SbfQI zM3mCIdh#7GpDc0y&bjm{3Bm|UJfxmm{9C?o%65G~5703+`$D@HMW1x6bO#YKEEu+Vm(Ml)!oB#eVq9Dju0|uD zuvmb}hq$_(XFQ8#X?Z1D5ld8G!Sz zx_7wg2`59=+NbEge56@RkAV}9B_F%ObM4M6XbHgrqPtw zDFHaV%+Ft#jI3(AJ`sQb;{X`u{A+{tYwr2;$-UL)0O7YkVI`F=+buT4_D34l0t<=NxCm( zTI3poixD~-%A;0Cs?TDZ*HiYk3y<64r6sA8ALgT7{9jZUsEZRc$cHd-lqcp$eHY3A z*x;BQUsS3JtwE$r4*>+9g8**FN9N;6Rjy@k+%|dJK?4G(hNqrn<@Awd7Qdr4u*1%d z7VJqhpJEn5s#;E^a<)8$dMjKAXtL?Z5>4{CJJ&p(b{QHQRhAe_TYt_4Z?^P-NZBtv9uWbEuqidzY)N*b0mKugg z^6RJlKV!o}q&Kz8p6!>O`>XJUe=989lJMt9{He~5B$0~i`L49?Xe&xFb};mMQvf^u z%t}<^ituDn^eJtL*rXydK<7%NE+nP_@)Md+px-gc#C)|{YK5_1!`Shi8=Q4OS49DlV$ILImmO^0B!rZlIuHI*7nN``*6SuVqsw zS<_RyJ#r6IIvIf~Yi=4M6=(@Y=IZ{DN{MG>vT&`M!o|8Ll9jIQpHTUp8;+c`pI`1T z?eC9{dU_g;2Ib3rX<24lzx;M9lV4N-(kOa-WFC``uS7w{ z{eDF6$x7P&M@$BDL~z(=$CTPkS3xt{2;BMH1A~E21&>|qeAxbj)0cXYm20NSxfbka zeRhG_skAR1X+FLgl|9#}9JuV2wC&pGS6|BnFjLSzQ=wf_n403=2-iMz zevIy7>1nZer_I_fM{LlNwKguLN%zfIiF=AKqY|af(Em3 z!>#(6SugVQXBh6d&UUGDfkfxR<@Gt1;#ev?R$pQXL>IeAbZ%l;t-yCFN zYvF7Gm~wjlK_vS>7Z{j+^SAz2Yy^~ubL9q*BtQT+W&U;7?3X|8j~`UAH8ydS_{U%U zSGxH7LT42QXH_CWY>pMhkubbW;7pgH92i|RZ68Z9S#i^nz^jj0ksXEolJJIn54#=y z+6XE!XBcll^&`h16KB?F8OP?}g0LH+6kR*2Y*uHe1A6pD%n)|F1hbR zTgTP`bw5nHgH+#twQKl8j40Hm6qo^mFT0TA;X2hIMr<&z1-A{&HKrq`nbMy=acWZBFfl98Tz6y^&@Rv zot$%v$vc$?;}bDmMBOGRw+I}{ws>$i5yyA?6G|2nzY+CsdYkH$u&`JwIFvdltZiT- zPmOU8-+lrrFm-W@1kO<-uFYwN-g$0n>4Fh#WU`{eMioQFpyd{YNEYOE>}*cGM-QF; zsvDvm_*+G*sbZR{`5|>#X6=@8j1@V#Gi3-kZwmcKlk2kZvFAMg92eYyQK)Yc>GJ6j zd9g)`>@wA+6KdWR6vrj8gNa~EJ7ET}w}O67yH)Qk>faIXM@PSl9WybH!u!Fd? zcX;qM5IlixhZCA5kyp~LfL-&=uAv_DXC#_jWRVPpi|9AhBQ zCgz2qU}fZI7D=AwGKF?ROQAW$O;}_)Ypgt|;&>WJ)E45TG@LsO{VX0~_JleaG!|D- zfIsj~_L?nuaGGew)AE%bq+b?DVfIsflB<&3{RqA={(aP(qehgkB;ovijgjtP+p_`N z_1Jp$tbN}aq)%=fVfoQ6_1=26taaa}&S~p}KPEMEoSzNG-R+_2qo(h&HM<<^%1N@? zRT;w95vKeFwwE$Ww**wxIQ2#8iT%eceD_qKAUH@sJU*+39TJpWuufN^w}1*B!}Uf2 zOI%9lL}2q^=NbfVi|`J_pL|lukFVs|6N98Nbl7DBf40uEYn`046`K8q@O>o+w4P0d zB7?sp@EM<6X$1ol>MMu8j->x3z4dSpN*0=#$z-xCOPXA>!!xCEX=pX)7#_Xu^sAfn z-EgMfhDs4~E~iYcbiz=h^w$7e)9Yj3f5LAb1x9pdfYfvfXnOv&0{!2DiHbW565WQlAKrO&`y0XUz)UZX>#x<1aS|M0|TpecrZ`ldGkjmjxZ zlxIPB%Umpl95S_B%h5>)5jlsJ4ly>Mp7#78r%nlzQ8pe(qRjaP{jvZol)=ps-Ch_v za$GwPIV?^pNTGw$2;Oz-6p96$Md$BVTU3xB>SD91j)-Aou z_?ns1LpO?Q83?Vtvfv_=g~=0Fltqe93_si?>yr-0;b0WX63D+(O^i#SrNfF=vhUuS zrWcQfsw(m@FgY6PGo0_%H=B4`mkRIZ0wIu%@oWd_$bCjA?;AWS*V&!X7;ZZU4^_AT zw`psw3>Y&#C&lJ}P+QGvzC7JEuT#I`z1lmEUkmM2?P*x%8&1o-C{(1+t2#U@eYj@;TstZrDDF0Yw(Zm{RG;~Y%yjE%=vf@CL?J34@tc|l|Cf)D zeknNs#R%;s`U{q}Ir5h`d?#AHlwg-X0*Y2^#rLxN#yF>+=baiS#vY zapuDmRNvSPGxaOvZ}8~ZO24cw+D?*%+B=5f+XdO1V^z%Wd~cy0TH#knINDD?>D612 zrC75Yi@ad%HnZz4J0&iu+ZT$K#%?n(cv=mKQc0JR_> zfK&o1lz-L#_}_xaUp4OEj{hHue!l9k?GYQ|3ZSLk&$$TBJx(P|Og#dox(L{++o#UT z|J*A=>>@#3VYR=;Ej$!=QYS{=A|YbI;WYLo+3IsgI9dQ(DF+>+k8nJW!iHvQ<4UAD z^+6ux&Kls_-KJeMC4(4=#w-9xLpvj;57z7zqB;o}R7+<=qYho{m1xxnw{BRNabL3k z^yzs2Al@{lCE;MV?p!DZtz~sL5440zDtONG;=En;_G~vnD>G8|Rfv@`n4o5I<)cBud@~ZELhswX3p2?BLKD zUKpP=fdz76N95fOc%qJ|C*)J0PQ)FJ9pwanD2l4E{>H}o_5B(A$({U{HS8l<5)1Cp zpIRgmz|`6yj@VCu;>|`?m7q|XDx^Y2Om}buu)1I|-rn=fftF686%!g)1VpE7^T+Lx zKr5evKDz=t;KmpXzh;@loa}Ih?su2NNO+L%TrHi39e3AD+lI$ZnNdgn*dN+!dVkbi zr;Rc9h1_N7`_G{LXzJ`DZ6Cfme@UFYw#X9t$-Qga9LG!^h3v33MET|B`csIaD06`GkkU|fhGLHzGO?5v!WsRo9Jg3Nkr#< zGLGv&O8}*=m~9zvD^rglLnc6!Cd`X6Zz@bF9w5v6Yt!%*R&>Q)i3&=39N2dyl=N zE7m-c-Ja16Ufg`TPxl;N9v{ETtoJPUA9#DRYmMyEt(-LK*6nOnap#^)T1MItR1`Kc zbjt0qPwUwZo}b^|A0KRZeB?cn88BF(g`y>mTS(E)gM3|@ufhYm>xKI0V)!9UEq=+f zoCD5a*8%L*CMRsK&vy1xC|t{$QNl2CuuGR0sfs3>YR6Veq~uSb^q+(e1druMcQ7{@UMrR6|@u@h(;<+ z_yyY<@wRDrE~aF-@ld#yS6BiGI@}d?uFtsD?-vD0W-q99yGTEWxHaCMvI{`k?U38)ApXueY-osdYL%Z9SiF5hzq?^FZ+4(O~nAW|9lyj>si= zE#{30*^-T}(J^K2jbL`yTc7Tbz^U!+1N}JpLLi&tzyZ6pLmUxse=%*%gm=AUzqQ!N zrv1|gQ^bKIRkw0;Qpa^CBFNvLaL0LwLszr_jyt1m?Vk@A@Mix;DoFnA0lNTt{{Ne} z@vj7sKY!wX#U&EsD(_$b>=}UsTyH%XHbt!@0bHK96OuM<6BSm3vo{oKS^6gN{rDY_kkO6m;t09cXF5AzN zIVTe+bzJ`D6}b~o-Bwax{RGF4D5;E<1z`YTrHa{6*_;14__#f0w!+#f!2)yn^;?$2%;r*_0o@( zg230Ff;T>DrQp`wp^`+#%;gY}d$4&8oKZ+*_Iim=?rN3s_{zrLTYuH=uC(PE>x(Cq ztFcMp)r{;DiY2W@koZvN3ei|jWR*Elq^ZJoc;c+pnB+VSSF&C)Z&t1cs(?5zSWl&Z z$YK$h#d`6VJ0G(X`Ee)!uW$goLjN0H5&qL5 zvF&gCYCkvrV6r4q;9H=UJjwTrs5vZHDJ7*|OhljXaB-C1=+&CYpp=G}_Z^S-6(FmA z0wvMI(X^~iHI>m3hBfFD zIrMw0dpsD$k2qfeo4pnqms>pAen{rxyKGP9gJc(pFvxPrr03=sPd|-4?&W{j zO~ro4C|@WNW2*&4zNXGJ`PTfPvOht5vt9SKqE|zM2Ei-&34GP;HrcwiGrV&iY<}R8 z3ARhQ1+9RajmC#*)1yP9S7rBk2FxHaHUo#y<@0`q2%-}Ua9|VA!-yRm=~fQVgcSR9 zxv}|T>U0TJRYA0yJzx$j97qoKDZdFpdLoWOjGg@Pm{GSo(UukRmCsmB%8ZeSqiPgJ z)F__bI3y-&gl4~dJRJH2<5)yaT!@KmemiGWA&gwi6F0>$??JAfs<-D2`>vlP4R*hnpAp{;rWv!H}J!mJI zz#?cEy}{tI5!UmzH*_q?0Wjw}HT}2OO=v@^wfY5|aRw95&#K}ac&lIo=@Cm;EUCjp zZN!Aw&U1}~tE@NY^*0O({kx4joT6q!X zK8re`&Bv9GY*Mym2E;wD@q=p1^AGyR3d(RQbc=z#pTLcl=OKvA57O`Od*J{CpQC&g~XSX+V8Dal6ch454vkA#Re^nFRl$0z5$1RXeOs*>W3F@aUs2ao4GU~ z_~dHP_8kE(SuN>z{TpmG?LH7!f!8G~*VgRABUO7rx+}O8>t%iBawetj9=#+>WSv#= z*<(Mwk#1;XW~?zYJ$NC`^caRdB{#>y)b6ZdEi3 zVOhl5rYLKxHo~`QX`Upl>rdcVmkY>ocf{H}d^Un5hp=6TQpsBMR%%1#|7ArZ9O3i& z+oUZ75TY4=<1rcixvv%-CnpCW>hzx7qs}$ep%}Zl9bV5#ir)$V8zx9#~Gz@=J=D?^VO)`cKWc4wxCe73MT9E5Wg$ZQFou z7Ey6jmei_CRDF_#QH!rhKwvmDlt`!5Vt3X^iM!@{eJG@ztU*2+-h`ErxXHVZe|kDB zx}TvdyM0i0e-Z2)&q6R#=9CD^f`M=bnwm`%BBR{?xGIs;vv_~689lTXSgMo59?Ch= z0^RpGWCySAEE^|E(XtLfA!in|_)H3~Q5Oo$widUuD1|(3HhqWv(IsAi>+5%oG~4IX zaC&zRW_zM)8@Jj5rkRFubLIRYw*3?7MpwFnhGj+ka*Ucjx;Bz9YP&^LN=OlS9Pn67 z>JmBiY-iMY=(chpsyQhL?%UrVWoYU=tt9=g{!l(hGvtZaC0r_5b#M05gfe)8}ZN21o%)K%MS zrud2DiM=NDib+hSp%?zxSx5NFKNzDRHHv<{v{i|Kbs;B4A|!sLO0Bf1(a&fFv+;58 zkVDHcditvD^2~d!aF{Ju%_k%t1sUImWW%5APOvv_$H()1ObF>QQosp2fyM)>cu+wj1$;xCP!r78ah)OQ3$!|+}t^z8vXJh%V z0q<0-J6dnO&)irCkfFEd(1bd2XeW2zsh{d9c-TaYlz(ov1MwP4tJJ&rcXmNQ!WAIu zN5LT`ux`!`6$qjHG;vl&0pU?vc2p@VK=s?rqZm z8+wREd9`QM_x?sPDk-5mX-H9It98DSYO+`HEjCl{nBLtbJOgvxYE#l!%re=HLHT(>J?7@&wZ=*rC43Cpjtl39?OE0}>&0JaJ#6bid~pCvp94hg z|8?Q$zbctG+TdGS`_tyiU2lYD0GUVZuvaWx;j1uN)@Oy`>`-MY*3h(^QRaq5cenHv zm!jai+c9iLa+L`oM~@})4?ki4I>Jwo$+V!WbM#iPy|hxN(+onP2Nth49Q z_s_CiTN3DGL zczPHh_3J$#7MU#_FjNnetB|E zc=^1zvVFA0p#`<_O_*Q0K19&*hnpaPFZ6SiEn+Y7?4a>c1C_LO7RA={kwKP#z*H_W zvzF$L=7BL??#%4Kx+DLG6E~%HQR0-<>`;`4M3T6m3O@=RsWD?Y3%2%t#fd4-(=X8- z2|^kg8W2+G0T2COc@F>e$dxT@{-br&^`>roWzCvF&;Eyjn7JzFAe41HE8+1zmTN)7xhA@h>^RL%z4)Ljzr-xEd zu_?>-x&u`W7{fBR!R0Vv@nWedm*@7@l6`OwPnW^9N@FA6ZyT3;t?MmNzTmJy*LQLb z+>^U-I4oK$SmEqElG?q;coRFCu0XM5K2#1Kp-IQQMzHDk23zVBIHSiKdwk@3w&%Uy z4iGVNBgJ+P&@-k5bfnV&y?y6iNLl_C<4xAxW#^u=gJ|r^xY@4&c?TcYbtpw0bEk=9 zpA_0`3)4JXw-*L%s?MlU0b;a_&j6((n19CVxyEcgIDldK0EXrKjT%PK$jHRn#PNS- zC(*IhZw3wlbe#G0psZsc#z6J>%z2`qA+nRbyp+8QGbv&U32v28s5uQnD`Rf2&mCu# zf(fxCv*c!*aH8Sl@8vfXQZHJ&G*uP=1}2;jLRBe`&OiGJB^@w?MVU{xAVhOhB&wBN zbJvnF>kyt!%Q?%z5H-n_Uit#itfKvHp_>L!lllZmpoJy5rmZ*nE9K)~w)F1#viW3M zrHjTWA^nkM&Q8cz7%^dQo`5{RJ0=+7XCBBu+DYjShzx_0+5`jj+%4@R?7LbTMD^97X@F(ypi+~GlM zq)SF&E6#jk^(C%tw=%uZ24zZQ5_hW)b-K2+{GHv(0$MyyjNzJ^x)Ia&B?Yw~HHAGSTDb7$X#iO@A{x(K4ZjoXIe&I2()hJSj99XOHe!DBkX zAui^y&8oY}RC5}3Z_27jZ#k`9BEQtsH10~lCt6d4UD0+8M8lk5u zO55}+6NT73^O86$2kxkk9D+>mzSn?yFwN+lbQC<3nEilX?&Ot+8>;wVnDJl}iC8M; zRX^jq3k@R{2qv}-HbF08*i1}RL=btS4%vwGFpM8gzKm0^p$`#GL1i|$wuQ#>0<^## zsOQA-wB5|;%oAqyh^P=ul!S9&BV@j^E`43t%slV&2eAnBj4T?k4sGHht=i=XD4I?= z+feF9y`Kq|VH4nq{7ve@C+V^9VVL?y9m9||t`%LCd$S2jCHfiFA$4%z6`2BHD`n~$ z9T0QnU}L&cj>h{9Dtu`TeV&bQ#6vN2vA0M~m-Hvhq+z~)=n;6YIJ}Q6yq6o{5S8sL z!j~#-NNbYEU!8AqMVmWs%)(e-SMn?yv$anwyp0Xi&HRwW#M4z|WVs{QYSSkgrKSRp zbYY1FVz|%c7GS`n@`a{-iP?-$dG|)*%cq+prn)HlVM->IX8Lrt@lTjW^DGeNZR|cH zO0$b1#HuT>ZIkJv^&aqR69EYM`K!)a7Uxbl;DlSm0bVQq-_Fqe4*g5OA(JFj*>K=H zfKB)vdxyM9rs=?FERa+0oR+i_Q*ggZ53RwdK#K~2k7)AyHD;*U2){njY_Zr5h>pGIL=wp#!- z1OOwWte^(;=o%{K=%lFINQOIzhInd)hP67~kMBIvG0eAtTWXIE zp(R+^CvHKnMr-+^sppFRJg(nx6bh4{YZB1A!!e6H`sz?Fvo44^YAd}+IRTVGLE#b} zB&%A7E(_xXS=6(iSu^rMp`oxB%#AfDa98faXhxw{qZan=NI3XuYa@1oNG3QzXhWx; z@r3&P5%C_9P9 zc>-DFJuTLx-mLXkx#_$Q7j$Fz`Z?SaF6z~aj%U@AuZe8TkTgU>_HB5Yo}#m|%sF#{ zWPDX|*FZ|?P|uQ)bY}$3(?aunfFs>L=49Hg{VZILY=jLO#E{WoaV-(a0*N`PboZeD z42(k!vmf8GI>T>fbwNiHgTGpZzcGDw2jOs80Hz-{)-9SSuij*7+Ydv`7}%pf&En%0 zir%Fz{9}dF>2%x;JArH$bZJ|=<1_7`F}T%|mC{F;Hl<*jd-2fOi0T~Mx<8Z+Xp}j{ z^Xo*l%zFvyjx80Fbk%D46cp^F;NeDbjB3XAN_>}ybw{i= z%s%Jvk;I=j>Z$)A;_cW@5}RD2c+k$Z)?*TE)2c7i z=+sI``GbjESOSsj14qWfFFk?UoW@slYC| zJ+=OTqVfpAw)rfGC@LjRf_ofqzX^RQpt%-E1x^~<^fI`mFowX|7HK0AnmM!#j9p9# z@kxFYl)^;qObm>5sVIukOn`Ebe56Ht*!H!7#M85G%sD>6EDTw*f+mgde0!Fmk{m+o z?g=zVQqs@J6`V?VA3iH)z9lo3MKg;>zNC!UI0Ad(%oPl`t+L@MUWuCf8(9S&xf%eH zuX6!d-eDy8R7*VE$l@g=iJx9jDr5<1FkeI+L&W3XIFv+maEu$;H0M4YrM`LStf9g% z056Aje=QX|5Z%0+O7{r-&$m37u4(#aa>d^?xz*n$=Y8vXL)>2f&#w1%jO+xb%sIa{*w<#hdzD#Ozu(6A@#7%Lc+H$ENa@A(!@SU8Q(54>pkkVW|y zL|U50PYVF0DtD~;lUC7EU2>hIUF3_zxjeKNvvqDx#3kI!_N(ClmY?4mniOrVJFqcRA0XXt3Y-Tgpf>7ef@NQx#P2=JGz@9pp=546)BRX zJ0SiDHd_0v;)Cu;V_8jAb>y7rJ!>6Rf6Q6UB;98u)X$RCtjvwo8dOwNJQ$0uqR_99 zSZAhYwio;*ku%@zYr|=10^td!=VjvU^8vq&7k?c^X&PeX_!sx|+gv@WD#niy=u)pq z?&UkVJ&iv!uCVWp+;`R{BbW8j$C5s7hl-cBUq!j6BjpAPgKrY4)K(A6%PrWr0OR^< zx^l$*GD(bPHgymOIOJ`T$o?D6gp7r|iShrqBU(Y~ZFsfvh)PmzL1Pa;Aw#O)mE$Mb zDpv7cLguN*0lTEc&FnY{oG3_rbm5Zc%!t951{)Luo4%1!3)Te@90Fsh5@uBkjr(O4 zhSy9Q>r5z!y&6RuX4&4LJd&8&>^?odT@a`G>ub1{At|cMYY;DY`Sy$5Pst$gEwIbd z>}n~~JE_iauNXPjMQYRc;P2Io5X$BT8H(UH(TViut(MdRvrF1mX_hBEi)Lh1ipS5j zd#ZZ<^zkso>n|x)%8fG$bjn=AxxjgeClzDWUvT^O7@%bfQdz0bmRH6%b^ zAgl|rKnzJ_#pD}mRdnJE8t9nEOn|E}e%7bRm|Bd&&#Z@xsPs2x?ObyPtD^Q^VM2Q; zy@gISO=?kZi<>X8YjW{KkqD-fH_IL#FKOg}BB(h?Z}Ez}^$WR2+=-A~CFV7S;HHdU>&9sxO z=kIKj$ofz`5*n@Ymn&A#NrQYFVIbeqvmMtZ^QC64x}k)=^Tz6GG+K5kw=V}jyxzqQ@B(T#{57R9dCUy}(YK z_s--*-KmX=ce$r6@j(mpV%LXmqjUR%G0+)nK-}bpkX9?P}j&|3@$fPnmBNe zotaKQL4M5MnlyF>95>recWZQw`%ICL--kG7KkW{^0p70C06*BJX%|K#L$MNIq6SfH zzT|}t^2M;eqdQIs^IPh>{ab?#N&#R;!x3*iE7!ZoRd07Tkn1u*7vDDea8d%>usRG@*8=@*u>1y z#N^K$9~~{2iAeS#Z%%?-7jO~+8UpR3y4puPb-+;JxEzR=2q3-W;@{ED%?KyP%-9DGIfTtt zn^Qai`a_ofu&GZq>CCc?c7#zxC+&qwOTGO2X$=Pi1ydTJyt-AA8ciA{|6Ud&x=j!x z7W8Q!HedLPcI@P9Mu+9`2`^$hzH7S7Pk`BhSHP;^JIQ*m+xkQ1OrLj=pZNHZe_tgtjnu6Gau|4c@ zkL;Gs5hIcnBdJSmxP^I%p|+ZzK+8!))+5NTZ5c`%(C{1egco4$-{D#b+M506?f~G( zNuU6LME{5y@18Bvh%f;o!s%Xw3=JVS>WqizucPg1^R?jYbcz_$Dy(ra-R|YftDSJKkh6QV$tGvCxA8G3 zCm~Bwi)`5RwuvsrS8^f=!RfkJ*%moa^G(FTkIzfzMld-c(8UgDC^V?7E%|}q{L!T` zz*hCJ8SRZ(AwdIu*ckgb-tUyMXuvg7-w9%mo<^JF%m88ZMDkTs)h1d+CP#yX>_<-W z+cX2Th8R+%?9oEv0f@E}0Em#_MsS$lGubA{qspf8Nf=@|*Aln!rkUnK->HbhD;OOU z#-4D1ZC}E>*p)Awrq6YIq;-Y=;L1lhC@VjRz@sXiITXrt7H>TsXWfC9kXXr?DMJCc zBcph!z=VAnhq1ii6(C8D?$8wkeCF0t515nz73NoXPc73O_h@d|%x9CRR?1m($1G1s z_qnVfgHE*!dQ`tb4!^W%jXK1!Z`Tu;f79^NCbnkIe;fX-TX@syemk3x24XBcT;z-*+TYe{xp&O^MV^DgEdno6%LA zSSg_kfW*QSpi?6kH2H&ERe|O;lS8GT!9z>oqitvvIgTcaLsIt#=paPrTT8o*Gkg1`YVHIup4Yb*w~0Cl z$aK)pvU08)hcBKuWeVaQ9N{}>oKxV$B{Gat8NIS19TiX*NHtp%Q~P4;<;)Z06QjA7 z+vdtiSL#5h{I8wn7oqHGAERAkrB3D=?dq64sxPNzR@n+T?ElTpZ$X;WH^x(2qMi38uz zHQ{RgF0dZ%mwn{8yQmUW-zvjON@&hfxje#?w$<@lptS(r)JS6gx4^Qk!5BSm%#C)xRiw8fw`hC;{x6`J1o&uSt7s*BjBK@9Y^sG=UAk(~-7Hp>FmpJe77))3qDf zp%oz!)lf!XU!kq~Q%zujlt)7_M4Kx0lnR+MWQb!ltA~S29Vu#qV|0^*Hu@Sm<&su1 z^iVBG-=P4gvX|u!qe-)UTNSl*4+vhoLS8ILtCF(3(1wf7Ik`g*02U_zL7oM7_wg<) zEy!^Tg{BZjP7frR9F+dqgRWJEKlMm@8n?erwBQ31moIne-mcl_^H9p2NlPw~))&b; zmN5bf#nIo?T`SccTTpvo{Xs{iq1kWcgI(90Gt3X1BU>DD%Vas~9g|`azk~IF4*b1E z!6M(he)hnwtmiV?a{E)HvLr4i!9tm?d(Ciz+K|37E*(WxoVpJr;aKVkh%?iG69KvcrIipTEM72-O5(V;P0ivIlRU*gk+?$V!pMGHa|dC5|<0mPAaY2 zY}CB_nvlD*Pn-O~vf6uk!h?|nqlxhuMXJ8+`z}vfF4Z937yi`Df(F*ihhP{Dg2)M9 z4opVOZ#snTm`j|ePnYrKVrWtJ)p{!`xA3($;OwDV_V60snplxBtT_b1?*HK~hh70X zE9kej_HvO0(AHZ1#a-6QkMjSHP-%vC8W$pD3@Agsi<+>YDH|y#Y#R~rE(m* z6ViaNLP%37i;&V__?@D#=rxd4LPicBZLt7@4uw;BH^JG$FPvrNv#L;jfa!mmgY{Qe z8$0=SA*XNcQH|w}88XQ&d@yY6JElDrNeG4Fq0OAji8Z$a(bL%~IDmuY-TL^jqT{RA z`v(bYSGvuQ@|$T=aurj<9kP0PzT0v6uBCJsEsYVc&(2vIRfSVuJzItsKoy!bhhEUj z9Y6D06k1bjN!flCK*AzW1q|umNLcKJKX%t+GWZAO0Q#uA01}oS!TW6jIPf6&|Bth; z@ai&a*Ou-O=|;M{8wBa@?(Qz>kVaZcy1P52yFoex=?3ZV!I?Ajj_X_NJ#+p5ev7sD z{oMPGD}DqhiT3nu30Y~9@>r>-2TPXQr|CF>=-{vJWgq<*ZSNU;4I|t2=@k0SL#M%@ zLE@@x4j;@7eAl&R42^c*qy=MiFz~X<#tyPbtDEMzsUn%)k~#m0YmK7OLe_jFXP#WSO%xtm zV!IX#Lm(V$<#^z?ySTr21Az$K1q<*Q{F|N$@Q88%v}^x-0LEX+_`d%rh)UTf_4@xX98{}N~spx{ z+^ErGQm4+TLD~NFYZcYDoB77!lsEaXDz-*(G&5{4MQ$;>G$mY;9~tVfo%7=hz=h1? zkxEsp4RXi1yidUn5vxgR<|k zuWIkdTw#?4M{w=ZG`B~K5G$O5MUgKW-c_PAqa%=Xoh@;@-{FQ^*S~H!m5fXpbf8uE zlve2a4wgyVyk>sav$3@5z@+pFz>~|1_b=e)`Oo^o^uM|PZFdzCn<zW-H9 z@;_EAO2*c9FSrS3hyMYl{EnL-vfyIS~p zzP#Wj3VQ)>?KvzX?}^duRa@?FGnuWg+gjdnp6s>__FR2u#~{HbCYkg_djK^OzoW^R z0|bGorS0xsQ@*KST+7GtmbGm@qf##e1c4V%5Y+^WCGwE=9gyPCYL6mVY<8cs-sKfA|6Z+Uk%#-fBor^;kpI;l%iQMA0M>nZY>yOYhFYAb4-bj`KJG6rKk%W_`hkVB>${r{uwbLpEeIO_};%_cRG z(nw1rqUM`F%MA5}y^>xw*j+qx)Ih~4g^4I@awDrE(p0zlF}g6S>hDRrlGx#)WY}jk zjeW2V!MzRZJSuOwH6fmJoBq0;=*Wz>eZV-(qjb5>35#X`f-dbT^t-5dRSSHQnI+)+ zD0{Inqj}M!+r)5Si1zSayqnOEvPj0_$(&pApimcwqYr`&KoVmUnyAKD#%|C))O*Dvv`}^sgOs6v9w62VwrL@5|Q6i zkKmsNE(Yy*@qZy1D%u(U$9b@dNWT3bt_R#5{Ff~mnnTqDo_Bs)b05{fP@#4A(ay6 z3(1hS79bh6q{QbvTFjAC0Uc9Smb>A*xmzuugDor(!rvW*Nl82WaU17V>;d3U(w!Ul zOr!qnn3y-XwycF~p~$Z+7^J?*fLZ)WGGu>1`b9DXCSI`75X8SohL@D?%O4@&%5his zG?Qam0}WF9evu5FYga$Mdm$Nu{=&e$kPNAAkv1IIW!)ikI#>?(;puaNYu@6r&&H5xwh~EH_clJk?nC z94?y2-?vRj@}b#(YAf`2%U)))gi>bUh#i3={x=n$gT9fuzRmx42J@@^fkHA$aUo9ZghVv+h$ra1*ip(RsLnm`p@~|q=?45Oa)-R$QWo~Wg(SKF|-00wEknh z7&o&J5gLFRR9h6JkP$)K4nFr|dG;^|q>hAyo*J;E3n6BJ;4*x12zSU?%y}(MSr>Qz zJvW+q@!O^&X+h*Cryo54Q+c9LE3IIZaX|`rI{~J0-Hg@rA@1s3?Azz=8<;EeDH9=S ziD*$GX5q4g0Ph)>G&%pi|CldgxX_6)a|vv2M)+y6kx-0PvpFp$e?n?UewvIkScoY!e));&vcS?{?8+x63 zui{Q~A>Kq0XDN3DEbN_S%|9$>3!hj=DCV=W)m$N?xD_YX9DL?Zm_K$|~8 zK=wjWjy1cmPUrCv|3y*mp=ZT2-4c%_Uu2ufh{-M@qH2u!u`I*h7wb4~rd&paapeNW z-I3_Dq+IAbd%!$R*Uf@Fudk(9cCXXg^xcJ{yaJlau&-ixythqM5uLUh~okFL;!ri-#329 zZ%ZP!YUsmYt|0(1)1p#~oRp}!(CgD$@4l3^$_F1WxnO`$WNZs94A+YVS+vrQC#`Hflt4Wuy)*#86odb3{TpRITp&qY6=$Y|W)RqioC1`8_MZO@mUpMtcI^@LhaT#5QQDbq+_L6IaG{)m5`O z_(&`_SbjJ4KswWPzDaD~!&kWeIz9Oxq?k^#6US?N`0E?9&K2_yd3E}8eEy%b(Ag|l zN!3(g<|?!Y{tB54 zkB6J!MGm%doxS_Qe#UTGP(3mbmeWz_>gOa)>GGFr@0YC8Y=q@HeZ}@ad7Mll>_C-5 zmzEf{7d!}*JE={_Ifpd(TSda^JXy$B1j#uYYWsfq`B5RKhy>dZ4AMBVwaQ&H4o0bT zd=o{Qm*xPQ3rUKSAu0!{yI!TFl^bbnLK!tG`I+iVwoYBEB>|}8qe}JDtO1c82#)uZ zc+?$bIw!z((eHyJF z`TtqFB3yV~69Sj6{4WbEMP~y?r@spWH0a(RwuV_qO5kT7`unq#-GNevE){{4~G*C;1?rh=4b>oK4g_ zsPY#$O?Qp6uHUb9VMC)R&_wr$e;Hx7C7GX&e24EKk)w1$?(E@(78(Ws3*YQ}2 zQ_NeeZ(st1;12w2wGWS7rL`{6Lo=#JDT~adjx+EjRco!Vp!ScS*)zV;_7s;}9MfmN zZ&mHrxr1u~TPq&x#FMffcR@mEu>ZQOoBnx$e$42B<2o_!w&sW~#L@I|_=t>4Cl1&{St|Oq%*?RN@qY;Wq8&&MvLaXx zhs<)`KyCdt{NO_OuH^x)+7I}={taZv^3SzGjJ9OY3%&S)y1R9+Z{!$HDCAlwSECv6 z%)*Eys@bG zTn0ME3=BTvFM{!VX#jxIS$0EuI!^W`ko>0#6|sN_;oi9$zu^a~vZ7!Uuel}H_UHZ* zx*k(t0xw~^Q@i_cPL6&Cda80HEjw}>7{ z6!H>n!r<|D-hF5<-j`rkZmf`8V3RWA)B zz*6fKrvW^+!JNdEm|k>I@LqILU|w`lTI61IQLq)1QY>s%z7=zoUrrCZ1?EBbpfT?v?;B z#>9jL-4I6>(#21=%(qSZiWhlHYWxR^8yB)YF@n(c)3HRy!#W~82nRJ)g5S&RF6vra zHgHwi{BOnGcjHBN^Qz3?QMBG|F77k>sFA!uPv1d8LxCFx-M1BXdv2UE21={mPAM@q9r#85FsOwe#S%M z{~{2qc?z!B#2iPD%Cf_&HFwk3bLt%Jdd(?6xTsF<#N-t`sCgJkcu#~HT+6LSU+_t~ zQViZ{W@LM1Yy<1Gj_r=-xYB_>_sxX zmul060<6mT{`Gw+@C9gK{Pgxvq}tWDaa3Lty!QmgF4RizC> zF7efFH~d#+ZpX0FEFvZR_g5=YgY65ILn$sxq3~@-&c2(NP1;- za6f9c-3gtIAXpk955Yn#NY=G5H4p17G?;r_Y^;q8hNdC>V8LOt(MbE5JRT_W9hV~2- zw1*Ngf9^Nl5%Z3ZUqW&EAQJOFtf*A2fVYm67tasqzAL@A;lNE_`)Apiv|%Y&0HoqD zK;!Vgaxnf5mlyGYze47Z%&fd7yTpL(eWGhWrK6_Y%`K%kTnLE*uQJq=5woSGKwpJt zWvZ=o<+GM9oLU}Ghaz@%+j7#P+n#{{b#Y&E@7Or$9E2_HTPZMrLmW^oszg;AqY1SI zrCFzov%xe%r-@7k)~)uqpY6qjIU|&qEl^o5whd|=O6MxHHP!53C`Ls+yq))YwpY*2 z1yW*u4&o=JcW5q3zE~h58#KCXd8t)0K~1>uggM4TYuOp0OR!(&r87@#tZFsy$1iZI zdU^|p=c5*vx>{j@;U#4y7!uwEHA84z<>Pi7zC==)$0r-cU>`qh*j!n|#Pk20gPMWy zTuqh|e?9R=23+oPx5zfHN)k+xt;(nC2|sXa?i1D^=I13dO}zw>`cRMu0LqyWOPY4I zK#8(vL1P{4X;=-3RRTsS6pZM2$Bx2XZ~25P&yqmJxKq9H@hMtKLDt;l;B|?q|F%s90hZLNKM!1wAyXJTPiVWO&gZu&Cg5Wq$^rolHBdX$q~a!bYN=>D+Q$>NPl5ae2L`ID4rY1t1!Q8gF4ujb^m zn}#IlUhQS)_7F}-M_rTw%L27+uQ@van!?i^rdCKQX9I`lB~SZsL!@6D(>-` ztU7z|858fW3_E%W&$YVYD0XqW;dXST_F`XUY0$!SlI(&2X?nMye-HYpiciWUu4T`Q zOY{9rvv?>;*y`}N1qOajqW`UA!*(0 zNM7cHvna`U&T^PiO}Hka&vC=J=(RO;J{rj1hO{2a<)X92(DIx?yf@H;L~GE^A`md+ zSq-d=m1AJyqv$qwP%(RF`MZzHRI1zIbuu*-e=tUwInjEQxpX9x=g&NEVjR_ zb{AD&*{0;=i ze-&o=J2+&FU1bd{j1B*QU?eF1r{t^J3DlvanwYA*UoO$!cNi?wSGEz-c&75GXD8`) z+LN?Y^q-i4eUItRNN~76{p$#ArYa%%Ol`IHzOt%b%Fg)L5ck^lSKICmZH#kW)IM8M z_H9O5mRpT+qBU8sXR+&g9`?xSj zS*wq5I+QoP3oT~EdlL><%KHy=tL%3JLGL8}`*FW(!{pB{%iHGkYL^Ndii#fIJAEB5MM1lNW&%~jSWpAOA!i(*>drnU`$L+0^zXl=ZPbktJqpWn^yiM?+esxFiGEN4_|iu9FH5 z-leB53n>*2iFENOE7z&ZZd%X1IG93z^f`&Jj*Wl&RhV{IV?3iNol{Y=E*=hi7egqa zF!9H(j*8pK!+9@ZgrekG%cmVeaVKSNf{mosxNfl)#v*Z+RI-F zd(M?3PrwQ=Vcr)Yb(g14T3qpQBzgPUN4nRXjfS?M&*LZ51erX`9*DgYZEi^F#7~<} zk9`d$R>+W8?&~pZOkfa-Y@y^)UiHc=a|!tenZRryG;<(|G{_C$pt!G@=1`| zHb+Ss@W<-!m3(7ZhZwX65i!Ww^Dctcf&%+Ct2m&&3E=9gL*{Hj@ZFVQR`bl8B+`H> zBVW9nM;gIVJmZ``zw~ofWTOLW1=J8rFiSLq~KRGl?WRz&gT*nYo@hj8H! z+;jp))$R90;yhg4iYB$%E}Q1rZ2pi%*e6A&E^qvQimvS@Q5u1~ZfBXoQ1jBMOUy|A zf@9MBO+V?e|B=-WlVi`DZ!-j`x)>qYeov}P@v{?T%Iovonwl}0swt8s8pGH!45L#E z<*%35O#B_m@NuO};a$^n4q@Tq-Y(8u{?r&wRW1X`@MU-42JQp^_r9yFXle@qL`&qe& z9VgEL)O&Tx(ld4HCV!>jgx}XVG+;yUJneT0pZJR-{9)j&TmYuh|KhFut4jQnwfjf0 z2n@^sIh3}0RpbRy1g7HWA+20$y1sdgQ zp#Nq7(m0gUuc|2qVldXqq$bs(~&}nKZoE zt4qYWC2Z+8v%`33j&YjdmtzcZ*Ph1j%W>APPm{y`&w;iKw~q;FPDHX--M%HxP+ldOh5~n zI5N)?=?vbm`5i)vixCl#n0cY7h5}cvRNB~d^w%N5vh!{b#aFxLUkX@ir&z$l&*-tB z<3%ZptkKx*Ahfz7A)r##P~IS92~$W*AU~ag$FE*3$zQ#eDfeK$R^iMDSpU}kkhF8q z|G5}Xf_vI`F!&$>#I|V&Rg&(f0Cl)dr^JnER0L>@=Q!(9Axmm_O{%bX#(aNz$0epr zoDUyDtLW&%=^*#L`&}@UcW1*{mpi+lo5mGk+Pv+V#p_;^d**hZh;o0s<>uZEt1FQQ zPdr}RFWHuEZ?r4eO8P0H*xrw&&)eFsn@*Ez;RvCRQiq?9G>hZoMs@v`*}l3q#76-^ z!UF`!f8AmKo!MRrs=o@U1i*|N2#yc)KyXN6>kUB}QNUY4U}qjR(|O{XeU4HdjwPRz zj?8}M86^K1TCT<21=ciO9XRh1-nvfr%j<|0nw8ZceIz8~Yi;S_PlYCA(> zTb!Ci8nm*e^cH(^q;Nmn^Q0{=O_YR?T=+SJZ6wi&z?2E)aY&p;^2T49fu#7=8$u&V zh>Acl$G3I|J*!|)6foEhXdkJzOg_q|4d69~1|}pjnCjkLSQB^0Ax&&R$8MwCo2lc1 z9}oo*VN;?~X#^N2vk(q*4MC;mp)qPeWsONY-X`4>G^2$=mmAG3#Z=pF<&AKFKy9AH z3FCR3LGyi|Budjba#oBgL6#3~`mvQKWAN0r#8OCdrHBxIt3dY%V8Rgpg z{>uJpNtbzXip>sJ7wgW@3VDSq#n<#EJhtN_HOx9yPF*I@664)YQG1}y<%=i;2|9=1 zS#o=CTj`TIU_jfoD6Kc3JoU2l9MG946O0q7v2==S)v{}o(_4!%V4N(@Jc25yWhP?r zwcF&aOTlI5E2#UW#wU)QyyWR@FhY`YOoV>hf@-ILRpCg=1SSPdpLPZnzn+ZLSkVSE*!MZTe2nc;$r$=^9AX;FB*59S#@f~o$2KFO z4NCPx;~Hb834Y7W<;WKd)32Rsqu(R;As~ya+(`>NFEnT?6BUMQC4-FhX-J?QQPuk) zC?gzqYh|&JzdmeDE`Lk7&6~Hp3`m*LWDms@!UF`96@wkbuQ>S4bs!om zdx=hKjj$UHk0SQ=8ExwrF`il+ga9|i#u-N|U_JZc0-f8-U^qcwx@<^vB1hrf<$Kj! zFs1W(xVsQMw96aMoGXKXz_>kz_9v9O0PiL`jnr>ruv@lUKWsd3oHL2=zQ~Ssyt8Ln zj6L$ctG^bP`Yu%b9xLA;OPH$S@MGq@qZI28$?~)Ib(?C^WTucZK4S+i7$qdCVVgdz z{=BE*N<1-GY*JF^RzJAvFX2YnBq}pZXiFIHjHcbu$3~Qiw8%!GH}FxU&sAPsQc*s? zW}|0&hxwuHW8c}8nOmU-ln#}2|CX5pJEn9<(o)ooX~~gMnk+rYf_14K1NO?h-5wd? zC)z0N?(mWeabY*k6hxbp<}Ws)yY|8!yjDXtqCMjX8%MKdD4zNVLGSGj3cSQWB0glf zspxQn@-Bs!Jrmt={dB3MLgD%_QIPe1ICRovZF<=7DjGt-unWPi!$ZPmwm)ty2&Lq` zuLEB2YB9@I+#bL7$A*xgAE1r%<8#>^OF1V`7rUIX@yb7+OkoOUR|#rIuSpgleZc;1 z$X+I-`wM!%cH%!^fbr)4enKi@;|PGY9slQz5jXjjgzA)m5=0c(*{Q;(gwoXeg{ABO)JBNYsSZG<-})3K#tBY3fQDTaUVAE+-f>@ZGEJ^Gz^ozU2r^{Mc4) zrjs<+wA!S~-qjN!opN*3vw7tMvPgDuLj5Vb4FjG04x>a7jYgKygLhy51V=)XZ-LUErP5)L2d&)|<*b^Bu1fQb^7Qe(3*D}2AGQ}>n!8Ii8nVK*ksUP#Q z`lv@G-7}~AnNc-u;Y$O@^Ztf11r}ke<5w>dac25*%ynypT8mg7+DNN$CQj7j1QpXd5yZCTkI`}OW0`U1;8J(?SvZy)f3P2*B+ zUBhp01~*Nf25c%W^tT~tnYvE-yW592XeTkR`GsDop6I;E0dqQ2)jwQqvq^*p>+`qY zho27E7-4ez_=+dX7l#ii=f)9<#TOwl@?_hWH&V;KX-OzIh`&5!0vithkbXC6L&} zoOq_LxQBOaP*2~dLxz=J?2qgI_U$2&1ga$HMjB-%uGR72*h_Am^IUaT=k?C^xeYn( z>V?}~?KqJ(iQA$yvACXzehIc{6^WQTOG=heE1_EOx4`ej@C>7iMw0OA4%*Zl_K_T+ z!V%PUc?f$qo)0wmC5&}D;VQFr{Nd_>{8Oj}Fu18+AR8{e!f!~ndTK~8^_H$`ksJhA zmXY-|Ej3M|moYp|>tb#Rd=Rb=u(AUKqIkVRIz{E%IkGu$WELgSj>sbuXWrl*8p(=lXaXO z1im^ckXP$yT10u<=fC9oX=98tBgECbKVf6%dkg!aPW_$jQWBnz{j)=$Ar5BdN@*V+ zk9wue<6ZhU`3<{@<6Ta(lu*s-w*KjK_mP}BsfXvTcgd;VD;yf2JfhK)9sm5Sk$&D; zcLLpT8`S?o)BW$7@wd{a=%!a$In6X|bGpN`~TadAkPzm2!hT4~mBN$l%$f@%5)T zCyX?5CPaUH&u+!B%_QdLE~h5Tg@hPv+A5bW>w#24;jXm%0>Z zuon4tdLgVcmR-85M#SOppBrT_WPe&3TV-!capZm>{&;-@wh+R&Mrt{$Hw0)eT zhr`;Yx!%XRnO5GRqw*k-@vyurYd!bz3^D2(7veD&-V|7(a#wofH>g4cNv0sT5+WHK zh%-?W!DU6Rg}3Z!%Q`as7&&c(HlJ~MJgVX7MW<^@rs>zeq-$xfN|85^PnQga=~q-T z+9`!9oqk=@TTx3!HG>b(iSe~`pxx@46WC~Ca6u^F=RU?Y=*rncjWhM?G<-E72IAJi zV^{Y1+R7Kz zx{_TM_m44_5*k=?okY6)K-rBHhr!=HTk97=Vs6yaEd?Shh*DLA*3jv&rO+M7P)`U?k}`eveWe=D=FH%tW2MGMJTG>7B4co>L>XMthhV=$TATNxyY|`0K$%-_lRZv_ z-I0mU)HBZYtZmBY)=eBJnOV1<4*j^C8*mB#W@vv=x>732HjIS8XUp+k*5&ewU=&}f zYXz4oB(LI~OAekCxCwlrM*Uo%?oV$Wl9OL}O*~AM~tcP|%pO&bmz5=*)h1_0eVI z$B>{dgj};+JPyi%gj>CdZ$YUFYKVc!`=>b^Xm`D{`wh$s!)jbjY)KdvQ79H7-a*m8 z`798kU~mKF&!8j)M-)tk$k8gcwTpXx%6@rMRF#HHFr^x>xkziU=oA&7F)0X?!p>U# zlsok%GpoXyQi$TpT6rrBz_RdqZ zWA;QAowuET{w3}G5A z0&6>pSVU_ugi-A}sN;bKi5GzUVM6RdToyf*LFg)?CkihoIuMcc6VaNUnDIMG4JMpm zGUDa~F~+`q0YQ}^O?~z6p#233#)wrX0A^cL5hHy{zWg)p45=}i}@4N+ne&88ZXXgyWF3<#@t+R z?GYC#LmC|H!F#CZ_e=L*^yNP%ezTtF(^3+_>Em9{Dn+G5r7r2Q6`wArP#!=v*Ow$} zNx9CDg%MDz704T;j#6CDNWx2fO`Diq77FfscqO|og;`)n zP>&}pr>U_pDUqjtZx1Amom@HN(8Tv)GENNZRnuhW;v3WJf$7Qm2aS%ocFB;wA7j-o z%OW`+q65v8KJrh_iN0S|^oR{U(=}k(dA*}Fcu2-c_WYYB4htZ~KLWgZ-2d*?13XNO z^&O2JWo%#S**`%43Ce#AOm1EVCYrg&z%-4g7E42~jZpf_pAI$>4%LJM9nrCG`UgFh zgpoBlLU?#`e?a!)0{ULVN=hU!LFB_af6fN{ z-IGKM=0$5+&1G-Dw=`B|ze+8~_8{OO8t3r7BRQO;pj0^tC@_;e=iQm@cDz)hsEH6M zh%U=}?&2Rz>k|>|ey+R(aePKCYG{5-z1Vrurg#0Yc}U~OoU8)QdONf&mot;$gNU5g zpx{;qYV9P`jlxwV2`wEEri9pCn=);AiYrh%SFQdq(uoUe2y#W0tu3}meOXB&iPumS z`+D`=F$dlzoS6a6WKuFQ(qi_J+sC8hnI2$S!FmCcq>C|zYc_VY{rEBL z2U6m^Aw6W)3i%K_^E*ouCh98qa;>$o2%-30r3gEpAeRO|hP@Z;(KMT@26IJJL?Ay@ zRBeD}T!^rKEKK7p^`iU$Ay^k(evKAUx7Fp;6@X)-TuBu8jOngvC4;n|u#AAgou=ql zc5YAO5}6{8Nj{!*)rzy$iW3Wq@wM)8%Sx;#!t9_>(FwY-XSO~_`&pELmAu(A0;a*i zap6!<-gXRD_P{?UBwVrH>{A1pU`aySG9AHL65h-6JPLBz7aqXYz@1xKYpvo#b%`^{fQ##zT}A`+@pMR zj+L>Wi<)+k_N2E$;eU4B;cU;1oBCCsKGy1)RlM4}=L_!9ozuA&e_I>Q7c%vR1=+cP z3P}(4j8z`3XgxQVE4ycwbRJ!40y3QZwrYpC{B(P}0k^^PYEeM`A9*fy`!|$&#zrA{ zKQK;|{C8j$X?^!Uzmxy?NEEwlasa!Z3pC;*{TBI6ZvlEG%964f612P!-ZC-<-|#AR z!^Ftqr~4={BKZW-l{eQHp5x5X_5tQW5PnrbVv-Wn)lI!A9)=}ggz@6kXD!0cZ@{Z< zBAieCedH)+f&|JUg~=n)UCE9trlP7-!&}8Z6_B& zZ>?awN@dcmGsS=Nm*qhkF;Qm%eKN428F zT-FS^GA^BUh~`b6M`%ZP2~$o7S7GfQ?+Dj@m0IP%L3bkb=9!r_{=;J6Jzmno3X1f? zVkxszGW9f)JpW)sHc!FKW5sz@4VcgNBNvM0%!n_2`(3YFD?M^z&ki#eD@(kiI^112 z;CY&Twp4fj1;5;mea9Yt%W$bjZr>nldoDX6?eqw|8@zhl85v(!6GFJKp$H;TCuy^X_TkGuYgmHxq!4l>nGG@IttQC?9QB$emjh}O0Nv4F+ zfvIluj8*VKx6CV??l5r(#>L?XTjNTc)hc2R}hQ6Dp(_W7*%VOmL6%6z8lK zv0`l?Jg}i2@^;`yzQq)*CZiZEbA}BIybu$3(t;C4k7v^pL(%Af*){IhrkV9E21)nB zS(vMs^t0=fml)P7M+gG1e@n;oI(ziz$5(Gj>?$LhWMHgvett6}eNy-q#f?{n3yUUa zDtKB;O-aJ(=Su2};|8+eQE`2*;ryw}miR+lNdT6hmO1NQ=$Y*J8!9BziDPb4d{jH# z;tEs!gh~3ROBzD8-IDRPe)mYoM>)kx>7#?NC2N`>D!tj3_6fnkdhIOCSS#r8o7;+l zycJbUP1$6_>0#Gz!Ve_7$UbGPfjzHWQ@tO&@$$>xecwgogNP%4w1v)QSh42oj^l=7 z{^BU)Q&~#VRr)-a*nNq&bVyo}^Yc{g-I<+Vg-khdEoZ?DdZ`y$kho zLwD}rtp%qhH!+pyX`?0!-lLJou;RPHaA6uRmpCGFj$*`m>r14+`_h--`d5HFa~mgP z2OA)${($V@olHaT2kDDP1GT9B6()G8dCRNqK*a|=rkUdy96uLt^m+8ijILeIW7cTtMo*`Tuob18 zuCtb?g%{m`sWWC9!-p-{!=H< z!Y_yq#8z`C^M&pvr+Gx)yat)CeN{Ht!j{s*Hv4wdnft>BFFEn}NZIAJmRf2&YYg8$ zGRv4uC*?w6OrAY%KT(Ru4Q4b&>T?&^B3BFS{w&h=li|JQI~+@+!hhcpH+a}@cE_Vv zSDoT$j!eKcDmRrE=W_q!w>4c%2S}v_5Jz}GcPa2M<4D-n+D_lWSjkq}*vZWHf2`2{ z)Ej?9i*utSq1#W0nRyk8D<{0a2){(By>vWxq#^`}Gpd_`Bp}*#eyer*9u%09n=c?9@}HZ?x(Z8xAZ1E=0Pw^apC&G_R6>_<2oXy|z)Mc{Qcr>j*to<`ZHJzkd)&uwW zvXlR}`9K-yBK`m>iM-^RKl#Io!@x_3+5tjwo?4=KnC%EA?z5@P zb_o>a**OTeK4RF&*66+kUqN-^<5DXs15tZt^oB`PeRa)g_w~8M!J_AVUIjf)oe!_C z_3C1e-0gyG-ur>+maD*&uB+tS$i>Y3@Bjyg8$y*ZAcXb=~cK%(|^U5S->)UKUstl=0+2sbmTHROn2dj0aJE zaKbN&gH{h8$cT&f3d?rngR17Xm#q|np?r@Q@6+-j80%~n$8+0vZ7bJAEeeizm zDs99kY7S-~pTlzQ)uL)No6apt(@m!~4rM?bUE*79*o9y<;VS!s&*mjV*el*7Z&8OB z$+5ARs;9>-6bTe$b@305YMb$*Jf5KM9p9>$aS(f@hGGyynt*UnYLV^j(UR=(xP^C! z%JJ|$4%PFs50l{SSf6c}e>}Vq=J`w@sKCxyLwF<|PXY7PG}A!m4)xEVsO&5uj01wA z1_+A(x+eMU!Fj>;{?9}4t2ByK_{G?7-9@9er$kHUCX9!5Sbs%D%4;X2X*!)uR$rx^ z4SnXy7Eb~pv9S|jYRbG-MWNbA!eB#bB@2-%N)=UUCtOp;B4^iXMR*&aYv_3 zZOK0%sbGT!GhL`E(bVn}@f$qZr{n!tG-45GblK!GL*#JWh;|p_`5|&(;)7G3vtAjr zntxBY260D}dXg?zRzp5}p5R~kZLNnB%xGZ={)HLW} zK=^+Oq;Jbk@qaEr3b9vmMQzw6(5E*w2nj|4(-qx3dhO_rpJ7K{?dUJUmTz$`+rI5} zmP3ajVc((CmK z2}1BSu0SE|=EwRmGDhb^J?^sX;^#5051Io) zyWViI6&KuGDbNmdf;vkYn(;27lXFlFeEI~ADy@_i&_$KNM&8)2g9Kst_OQ6gT{TN# z$Lwn(|Firq_0m4B3Ha2URz7Z`RFJT$-M~m8th5gXxmATHnm2%E>a<~=aSxNjpMx6E7t+uWH&!9KAx-Eh~7NYp6&`%OjiThH&W!-G5Rg;z+*^yesxJW zuVcGU=3?~m8qUd~=p$Vhv99JCX>sq!-r$q39d_oG$#5NnmGA-rb7a8hFuogsFfsO@ z=XwDDE7tFbh2MAq3SgOkWqsoptpDq^S6TfjAo+8ibPfY~dcVVhL}G_j4X$`lWkk6? zjd7#8BKsx-mFTr&mzpvrpOC1IkI(G9?mfbycSzh38q5dS#Zr=S_WP707Z8R#SWB|G zh>imtJ|B-li-`ISzFy#=F_C^CdjmMuIS|?|tQdOe4n1=@-hP zyzgB<-19#{%SgF4yd6@GXKm~IcsR30@ko`H`k?!Lb_ns++M?D4K;zdDV&4|2@t}d8L3xyR) z-BQ-?6No=-Vap4ZwZ$Zx4cEb@NW8WFxGQkUyK3clSNISJ4jC$ElaC(l24}C`c@e+} z9;U=oIzJ$d7zuk6R@JiPC>f4s!CqIQ=C3`+{gs&p*v~APs+2N4@!e-Df2O`BOjf2` z3(Bl5{!U4At;LWX)bx5v#0dhESAO!~t9zOfEFtk@ zX#`p2k84~H+|a31{a&2mSXXP_e{VkR`IOjTqP&U49dMnRmEBv{?M99e27?J(mXpye z;S!INHl~~U-P$fHN7P9b-Yjoy3*%H8GbMk#QU}`Xtd8ML%5j)Zl^|-cnqL0G2fHH1!8uMh@%BsJA z#6|L%7-wS-P}!!~Qn$iQ3^NY_7DnwFryRX-Lfg90xhR$fW=ug*gHPn# z=mW*dAd5>#4ZQ1N&{~w9uoqavnt3{YNG&p81EscvMIYGM3szSzt94^8>nUn$AR4Hm zWiVZ`nOA3SX$EdC@$vJKE-!T)A{!Lcs}R=M$}-(dN${Qrn8e03D`NCkAd2i1&l4QN zr1>?ofje|Y zq69?fsR6Dz?>!HhUp5Rl)kjoaKEitO4H*`KIsgV`|D?V-(pTe-s|o z`-(rCZ!Ri%@y&)sIS+%|o;k^Lk-556W-BlAD;#rjR7hFjsLl5R?hd`;*vUxkWLPj6 zU)4PJD*0o}4%CBKMAdZwZ`$5-9v=2L{u#5!hoa73i~%V6|FN%1_IDisBNq#6V-v^! zwY5d{uO9MG8(RTxZn!@i{Q-bm&-ZVgq+|l1;ty))I8>oCAB<7GOJxyjV=h!`(qLK?v83DMx9@O3rn zh{})FHYg6J2<^f^Wv!RSbDJXe!&DQ|Hc2&1J%rDel&Nw#xMlQs&s-DR5i}_zDriq+ z6O(~?u;jT^H!>L5Kw`MaSl!TtM{8@~Qy6ZF+wphlR<3mBH!lXo^gYp5@x^eC$3)Rc zZ-ZqpCR`n!DSB5(rfS9FD~3j61N%nO3$QdEstk&jQg|r+ip1S5dB2^k!)v*tiM2zSEL~n2!^>7R z1w^Qh2*@THdSKFl)?cJuD`0po3V!Kz$Vkvzl>=NP6yPF%yMORs9{ZcK2^(5ln;8EN z9)Gkslyt2C+cVyaRT@XaHi=n&{?hT1HwvYZ4oP83QX1I{GpZ%rH+-kqyKfr}g`{%O zw))OSY1!-P>+mK)XaO$Caje6kYYT?bUMCq80;r0|37h&zH^h=EtC|>F6z2-&EXe{N zth;k7kUmvJ(WVRR?@-atIv4MU#e6|wM@<{@dy~}G2FyWlaf+)e8c(*$7Awc12-Y6&kb1^Bjg-v^-3#Z7vdSt>30#d ztLpvM6IM(jTO7HU^y?A|ad7W9P(b_;1~kC=|1F%5vvdBRevq87{xj+J$)o+rY19rI)x=bS;UbQH6J4Znkh>(xM{RMLy;K>b8X z)JD_Q{K#`VgJ<#Tm|#>*OwyrQFDs9B*ePMz7`X=&9eYB*hm|yN=Q?H%D6jzdJBT-n zi)|x2yo%e$kZByvUMtf}_;$Fly5p>^4dIY4tkd9@LbNVW8~#<0=L+x9^%JUOwzs~d zX7qL@D1jsA{yeu6g-TbhFHvjZylnq<+X_C-#4i|gl2cazl za+C13{#4xpjno7+E?L)t_%+JXvy!T%7#jeeiR=s>>;rk2wJiw>^^|)y7XlHL_;_-ir zi~n`VKaGp}r>YSW0MJ_n_`KlX`TJi^`lGj_0Qie0j?Ny^CLX^(bpn*fe$&39rg6YR zF(#;%rcmn-1}{2+&myOHTAgBhuQ{Tk`sAi$V}+CpO_yTB%fEV&OvxkzSufcvA!%%E z6aKTHRwhplU>a(xGV{r*EOWkbznD8W}J6{w$@tJDoUPPAo#Nk!|5h6U6Ua;SFz>Q?e)H;tj{F2N(av%pU3+WrNVHszJ|TCO%G zgMQ=t5$h%UNwOaZe`^m-7VXPdgjn0gS(CZ?egCzJibh*T_ZeMNBUI3nMDkR1{A}X! zc%NUqCY!L1?x%2KI>1a^|CX74wNG@yq$R*UgBQNgJ#-e!YY<0dCZoAgwnVZB+-L)e zO7t<=oD))%K6jiy=vOJ*Fo}E<_VN^*ozw}VQ-O`_Al}gZt4lnI`sY_Ps1h^@yeE!Pdl8Q z&hOSG(zoEfY%*cxL;d{vn=KBwQi1Urw%CrIg{xsghM`g>q;$^>OWy@xGX;Jr!mS3o zAd!HB4Ek)Wix8p`^k(pxH5(07v&2bsZ4z@ZSlr?yG9SBP5!7v{jRzO%qde`Wu$0)a ziVH@=?R`2L9xt?K`)G>tMd!|sVl+G&sHb1f`)BVsw5n33d7noH>x>&e&QLBtt<naIHHK&pew_R8|{AFqb=2&Iyn;Oqpnlko;FKf`B-dw#;=M#M;C0 z%qyAUfs7K!l|mU~$^~=eKBwm?(++NfqUn8XoLe;~mop9~dcZ{*+2mAim%yTjwrNRj zH9(>Lh6@u}ev-(cZwM2afh-RqTpwJ}^%e}K1&})c7hfwhhZrO1xOmfAv<`%-O72)Z zsHi#gv>4vu;j}87WuG;oZsM{_Sr|Y&4}Jfo{AwwHQ3R`3NxR(1oGgH*dqz=UIlpEc zgv||)wYgmbsEUe~w1hBEUo$#)oe)JbEsAgLV}&6tdwd}&2?e4``j>g=BXm^|0x_*Z z(b^STo9Q$EMJKx3Z%%rM+|Ng&uFE9g0rvE0LRD7;xY?7VmGV#P?6P{C8=b{5>?%XN zR7fzpCFYMuvA9*z{p+}MDWYA#en|XJ7?-OS_9z=X0GbnD_&VW?^8-ragEv^y**1&% zv~m4sdk5~=PvjVv>MFRP+$z%iDr3AK6QD$aX3jdB&Kb9R8sn80q-$Yw3fUQ{mJ<0FL>SRrzlh z!GAeRRr2>*CvI9U=qEGT6Dq|Oc(^ME53}F z{G)kRDI4~QV8fA^uN{V>X4Y2vcN` z#7RIZWyS_VVP0}FxZIc!s6QFUX2{WmM@(N{UuPej0C*hO-5MB~AR;QqRdKx9`VIFo zUzL;$YLZ`T4rfqhUE^>YuPe@q1x)-yg?LrP_MKWiE0+AzI8Cbgx0(tobNsb<1RahS zlvS-t5q1Q#Bk1qjWG9qHh&^ZSU^85oWP%@D)U_9rr2G-2dvk)t*nbF@R1HuFS0&bA z%i4po7u3y%2ZZs2?6C*75w$Yqr&bmcH)Xg!RBS)s_L<FUx~wQ?#pXF zrqO8fxNG3j@dcUDukJM)%RZqSd{j+4AcYQ`I{#j8wq$syPzX}9RLD*6vj&>A4S_z_HvNl_lYKvT@EhKtwQ|>XE zWAR)b>-6EiKIp(3p(O_$Bo`_sZ8A9N%G{#aIfr$Kj6c**ynSAH*=WM;XYzzKyWU#3o-DqL(NDnG9wpWgFE@C{ zKQ&;?nGRuC&2zQ6(6GUn5srX^-AsaNr*5P1?jDP}9-6F&l;1%23wBrx#RcA917RRi zR_Z%|)qc**{cWD|Kk!Du@Pn11*&o*;P7si%0EqIr1_ao{^G1Mb6(wXDiUvTvbc;up z6ltZu(6EE)=bO?LmjJW>=JdLC|xJhzKk^{Dk+7 z^+TC$#r0)?{#VwFgaXEe0`-MU3hK6usFJ=%It(l9n$xu@AA5N|`|U@H6s^j=2fnO4 z>S2gPRaC~0gxO4EknS+7YTHGu645r&v{^~~R3MP!{dYnuAOT+!r$1~NT4kXqw=}hw zM3dJCg=votg$L;72s~d0p6#QNtI3QJr8f`LzM6mcdCefBze)&?oXvkjODV}byEer@ zkX~@U2!P1z&81dA-W#58C0P0;!N7!d*rx-0*PrZ?f7{yp<-7ilH=@4z@zc$XA>p&_H#)%`9PO-c+G$}kWxlY@ng}T!AvZh8SDkfZ_-zfaikPAnitVMNJWY%T3EC- zf4heHX6>Lo?ebHGVD02nBZaQSv>yAAIa94|;)8Lo0dP|Za^Z^qI24s`y;LSuD)8f3 zk1E=-j@`*;kOd!Q$pLf)$TF+4mdI~2?LccMSVg@vc|n;dBgPo(d>P z>v!x%oGjrD->-xkmkV+sKoWU^jj&NQ63vwy!9GTOHyq}0XwxFF;*I^TAStKVnbXH= z{vpl&2Jd`4JmBdJdL{^Tv;b9nOw&;=g>2JS-uGdGeRatCCQeS%k;S9-EuLjkZ^44! z#N`RyP(mf^fDAft`!&GdXR`B`H|yn;*-dnSc^Ll#^QcPx`HuWK>oL_fy?fWz^X?lm zJ8W+QX9~!iU}TYbiphm7U`7Wc((R1Xuk-c|8`X;jvi?25HmAdT;8uVu^2WR+O7VVD zQsZ^nu)!3dXU>McafRX$Qnpo^1h^t{L@- z3HM7F3JaL#qH%);gGTpyeV`6bHCe!v6y{K{Gl;O4{c48w=Q`Kp;G0DqrDPyzK>#Yb zmF65o@90fZS*gh3t;tZ?4Z-qo_;Osn815lbA7t|~*?nVsnoSrwrdzh|ZF^VhqO%1>$V z21tHh0U!KthogVF3x7_4;zoZ*`p1X>TV&y6gs)<889SoVkhl5eOvytrmb^Nma*%^> zdYqEGGa<*e%}&ks@{zSY8Ql*VqrAhRKgF_#9}XzCTuMsIB*0(i^YoaDWlp^P<#~t~ z&8=bF+@Q2gLuD^8Bu^3`9H%V*h?RdfUHe1)nG0Av-0x zQM*xFR@mLG1ejJaaKrV@`+9PWpX?i4G3Y{(QkA6LS26%?V7;vqvauG96!MIot<_ku zP+EKaL?5?r?pU=18G6XgQ8evd$GnSNNJ-PNs+`H3k)ra93j^sSZr5u#t&OR(6JE?z z(H{4~&h1P2x>l`CqPF^%Xy2VKNm$MpBPMJp%$|zt(0;BKuNC0DX1Vf7kaTRhX?UN9wW_ap0>p@lihRGo)(h)dv>+ z(mY6bD0o*hv!v-!rOF*M7nrWOeL$;4rLdQGQ7^&~ak6Nlx-2xmLcawIG_=G4$}+Ig zpLywQ0OPMNUEX2JhXwfjtbot|@8e}WW&2TWz zSPxUiOxTQ=J;GhUCV2N*0$L=xUxTsH1Xl@qJ4rvS>hi*mOsE%qUILPmbdhC6Fg$E8 zRlakL*UX3d4ruUtY%*RZ(Gl8So1IaL$Y?k-4(E5SZ^_H&6jIk{3<{$+6oC&>*LgSU z*@z@e^mAeL-56m-9^O3PojM?OjmZnEv92P*#lzciha?!F;5zH`?>EuIj>a1mn&{5yQ&FmnSCCkWT>hp6{o9lIS8nuA6rij>LsRZnk;zSOns(w`pUY$qY zCOmgfpH$@O#43E5XwjHMdF2e2B}gUW&isNGQe}7b%jOQp zyRK9vfEgJ9X8c zpQrJMU6fl|HWngAigaaUgk{Z1@uX9f5z@Wge6rcLV!oC(cg%_&LXR?(JTOQC5hB0N zdXnVqAeV#SFjSfX$pu%1oZ=~hI!d#|Q^Fs>_6|f(En9@1E*<+(y0XNHbgI>$Y`faN zh#GqnR^AqH+d(U8Xd2wMz-EJJem3=Fma@KyHhO-`{#YYSxs-Zml`f~nx+op|wJ^s7RGgi_Wq zEx=5@{|ey#)l5Ib-JeYr9pCd4aDSWF0LRB`U$r^)p>mv}~ z^h$z36-B(9$n9KtcaaCsnSnnr(>VfO**=Sk>JQq=1G`Z+By#PxVMlU)P)h!}A|Ss9 z=85-nMSvxPA6t=nCWh@gQ%6G~l1x^zsV6P#@cH_5)a!2TzGe@FNF+?7Oxae3oKB6GDX{M|$8?30sBO-2qO)1=zg%+kuT=&Qf-;7IihTRs8K= z{+O&gfp^LW2tjTOKizUL2%5M^I`~88zT(amG@JP84a(uEF=+Mgy!cXaBLn zEG`zDQeWcuOhu=RYWPrAuo%GnJ!-d#y>}ui!RUsILtHy?(;!Fo?GjD7F&j zHE4Yu)OGu#a|JZvSVwXz_+~DIVZHcgytp55n$1L38bAsly7Az6D}k}HV1kJ#ONvl2 zcGQ7+BbS}D)2zFcM9NZkgx?YCdpszQ-rAc`45b3kxDnyBP;)9kJ{L?DjbM6hoQS** z4aT!_AUdajCZ9?*(k3JGenvy3MrZ1{Wd89!>N|NeuRxI=vIAmL>X|?j-3-on2{*$_ z=IuuFDcD-Xa&RgznmdZsT%J>wzh6qgDfAJ0IHEQJ?ZaTw8p}8k-dupFyA~F1-8EPR z6*B%8oCpiAM+FWe{B?G9d*Joh_!DXJhsOPktA3E$n(Gf@4K{lhiT&tsLqW;ZDgo-@ z;UsrM=hs99%Nq8ez<2{{P-s$*mq*A5AMh4Kq)!9QiFX%xxF_J94(^$_d6%)BHf6+9 zB2N^g>Fr9RfMu-GYhZj~gGw5etzCubjzyI&H7+$??=!}kN=ZK>^YyqA7 zrXs-fZF`siYGmA}KADRu!H#dOAz^(;PPn9rVP+)h)@mLyk z^LdKRJRfShdN5AjZhe{ssFZsq>@T0jT-d64^fR-jwM@a-d~u;dMVOGA2?@M0n7L~d z5|l5#xTSmeB_;(&qkgUjfL$pdCJFvsmhwM+`gec+GtDJ{$xv>W0nuktJ*u95y(|sE zpaD8if{?b&CWG%3#c^HI=-W~_y-MEBCKh1(Cl^{Te>jV|X?NDK<^V0Q1`UNZf^}u) zJ2?B`mpiBfu6eNC=^8qFmw3`zi|CunZURna9rY+H8=kuvb5|P?a|JIQ-K;$mXp+h! zZ64XNX_VM}`k7*YDmLKdWKHb|AxplBU+l`#HJS`zWRfzaNW`n$?r5~K^vUifJ*=oC z^DVh>_rX1@8`II6mTP4rpbDwoq9>_p+xr&6v}#7Ui2(M-mo6xz5ADh@#2Fhntffgw zy~bNvT5*WnLCCu^Efqdc&#G>^hRw9JP`U5pfd8o{$C8A;G#*yHD8|(7)FpljN1m`C zQEUMP2!5Evi$C!QOst^Aio^TlAG{ctk2@bH56;^LCDDjGzz`^_nOeAAr4 zTEHt?cge?cvrh#{aEpZy&xBSva2q_U@f((|tc9gR9trr->4gw=Q5(yl`;lD(XS%n{ zk`S>`jdoEZ5pT1nzKoOPmqgqhWAqob#G{`+-(G$#uzBX)&Mt(L#)kb|IBq=*=Ib4I z=JfrShuxkYl!yX=OKANoFNgm>m-x%e;j|n;(AZ~FeXT!LGS}CiF9&eK4B}O=zBOz zr6d_0Zn=a5B`o(3R$`!|=)orGEMufhBtFBVsLVmvfQLh>>cEgpTzL=>7IZVax8MgQ zQg0`0T&4zrSp(m-SNrlta-S&8_hUgSX4BxyT+_ocTT7h@96i@ZiH@cf!Ugv*O`!TQNunr?ZF^6Yj2CG2!>Rry^0_M)uC&%Utb; zYWR|E`>=k(_bjHVb8oK3I+-Ur@d;STxN|v1i1sYhGtuzs|7Me}9^>}4c$d|~p^GdG zbXu9iy)ZRK{prY7Ta#?NT)t#F*mb+~+a`EZEK6aJc%RK{_qs20$`pnlM>9e2?DkPQ z_-vcvkGYH9s?x7_ccoIV8~_o8;DL2HXu-v_`CBBqv<2PjfoboJFRD^u25na4Qo%SJ z84axYMSJ^W*kF1_*(!{?8t)ft-5T~+5e|RR4T>i`7LEnPxe`E}``ga$|8xL(W8=Ss zIazreM#PSbD$HpRATqHjZHsckrLyE)0c4e%;PzWmhusGDSHft-w~pOYQxrl`TpACv zp^FZW5Ap*8QSyitnGB4gjKb`$?foGxbuRu7Eji*iQ*|DDk1V4qnt;(W1ivjACuYMn zOdNNGg=!dTqj2(E9v^1<#k3i*QRq!MT!UPml@8{!K})g}JBrxmOapT#SGBI?qOxTM z^niN3*w3#8eSNU-+rYApU>vYP%BH}EBOs7g!0MsB;1x**Mw+=G+@a=EFnW2Q^2^wH zu4taT3a|in>;hrR0t5xZYs*=qoD-|}c2)^5e0ZBoEZ{_937d!Z z(xw!5C@?ql*bwIqBwIgr=H+I9s+yTgYLqg_4&h~27##)18bPm7Ja-uSrhkexzq7IT z0SmxTxvIK&APlP!qTPl$y~sW{w)B>+T=5qcELY+4Sp0z>Ekm$s+lag|@Yd}jf-D#e zJ}e1bo{vQIC8wv1k#@}&gEA3ElDeUhCP}mCVNUTI)@3iB!I|VhvhZ@Ynw<>DcmT!jr}8{Oe}c`lX{gSzkZ)v9?PpPbW5xwh{4%t?-G)paS94 z4s<6o(?L2|l#KIhLA8Ov``jvtI2@;d$xj2j%D4ZQb$3%cM;k+Dz{>moEy?`vWBzH9 zNqJWU(Evc-VL(9s+spUMSz^Ea!#_=oX9Mc}69&|^L+Y6R;>w7JcWm)eRdkU`D!tg8 z!;(fj;`VYsm7OOX@M(ogTU#@~a^g=$4b6V7NFfWnF8WF}X89u|75r{uaaI6z0!OmH zJXY@86QxqIL(Z12uT)+UZAkq>Jn4RgyS=8_6!O8Hx`S0TPzo+~JNz0EV~qM6q?fCf zN!ZDj$Rl#Nonw=RNVWeEaH$fl4k6;}M^dvm5Y9OJsD|2`?#1|-ok`Tuam1<9koMYr z;++2_z=A*88FA(j1@GQKqu++_JezGUm^#@0#+)?&NvY z?KV9|j&nV<`DpasEn7bQNI2C~A9i)i5SLA5Lg^$jFavy{ZoMN-<_-wOpMQqpj2ST>V(I0S#1p&?UDn|H3%$>%BBCB` zr{kv+6BEF7oamrZ7&MuRY!um6G{>^X55?V%Mbh;P9ePx#7&$|uAv5SXS7_-1nhZ%w zn)N!83(A_R3H2-;93Nr8=Btfca{Ic|D*9R$0eXqZJlgo+6s0h=v=B#$pVL3uVZblHCAR(N;cddkzNay6+ zXT|i=d6$c+U(M^L1z&lM+EndT-By@we_%P<{E>KNaE~~+dt&Ihc>;*VED>y_tv)z- ze)AdwOaX(=dGz{gLWw2+TJ3zkUQV6Ani~_TJD_s`*U|W$1Ib>E=HG^yIuT} zl|P?vtSkYHUJNk$-&UHxfWRNg`0rToTc!C|Jr36n0s++!y3g3*x=Iprw@~TE3C*Og z3l0L1XI*YGbh+#3$*JZ{e1~HLLuj#0Ji-cG9~@$?&|S(r!o7-`d;*K4Qr9pe^sx10 zaK)37XTW{0@yx(dv38ZH`l1yQ##PpmDB;Kx%Q>n9U|b&SYww zwL77G8mzM0Rca|6%#m4qW5DNT2xSmwC<{#WMHJKYy8Qge1GY+*r4BDd-b?irR%Qau z2ho}2BAOD(wcQ+1Dt^DQgpQC3KqZwE0jha3BHEr-g1p3r*i#HPCJoN{AGbX_@3(0e_0gxVPvKv~BLZ{970=3+ zrz*CfwL;}M*A+;cl+H|=I(Eyie_4U|8|#2F|%|0eQ@?n%Lc#~j0_+xuQAC89bt5?!q|E@bfwvt+%Gx-Z*-`Y3%NoDSW{Kj z36UN_QhK?|OkXEUrB}*gSpbc&~cg{XG0Ey=}=;?UYXpEq#bj>@c9k5SGv-s_-v zc{8e#yt**g-TQu0BV(C$K8|t;F;`@Ve3Q&ru$jz^6eC% z<-P!k6@Iuh_UQz7pr@y!;cdQiOR}X4X&1N%Znhe5#%~3hQJqqeN+0i3wYs?`7f+cy zDRz*@g%FBE98Uw+e0GDC)2l@C48oKR_!0*mbEdIT4>&c@n~G0s*OESx(afFF&>M4i z$5>-v7sVt4;O)nJ|4NnYM_PAy!NK$S+{>>#A9e>cUR5^1=$^cW)aQ{aKF`Uwe>GHm z&`Y+e?Z>Hk@i_=_0FU1hWSI&g%)DY;8!MhEI_Bzi*dc&#IQA`hol9y z;=`t&OZhohAXdv9Fn_pAb(bucC0qM!hs=OgjR5r2GL2n3cZdA2ZFccR3%uUJCf)R8 zvKA;v2=ra*BtGr5(;%WVv%%yKablvIZc?*@*-}d`;L1Kap8#WI1_1+xStmk-rDnzF z<-GRfjqx$NZ6sns+uK1IOM%sQEFm~frE;{6-JH}@)r@Zn|AHa2VOv0v9Aec z>62&y>_a+O!-n}2irIB0ZV9gttKL;)@uKp@mXDw^#>IQLJ2oYL4j7`|bAVh!IEN8UkDIUX^ zBu6VA`I%9WoMQlcDa;JaTQdkk8Tq3UcXxY-`}KD+;D+Jrv=2f_E||pz5m>|>g*nNR z-=^>>o8AlPvm36JNi6vCsXbKbd~|l-cZuH)7W@)YYSVT&vW*_IQYzLA&L0Z)wP?Dt zsO>mDBXmR3Jd@pAC7XpQjBpA)4L+3bwzRA+xLtqXrX7r`k{B+LL-{0~vQ@O}nOwIj&vqyu3Z zG>kf#AA2-N&0x9xn_dv$s&Xds8<^FbB_1ufEnoG=(<0X2R-2%sjveUzP4NeUBEPQM zEP=}f#25!xzeffSjvgt)7YA|6scCbLa|dsxNEocQqubDtoscQq%zN`S!p%KwF;d%3 zs_*c!v*mV$ zNc2_cS&LmLxo5p%aj(rFT4vR5Bvk9zBv#LRTjx05tV>*4OXv*M=;4&O60KsLS1RCU zT7zt3IULX-KFb&O&(w{}pO;Bri0mioY3WQ3yn8IUedj!(u0gV5vBjtFrO(cY6>FFD zdBc>WJ7xa14hY2r*EZ5zS-{Hx{)YK{Lxz>m;73i#AR;K3@Z2~OGuxu`6z&m8xPSku zvlPh{CEEK9^jt;+5Wdib!G2CHfRuZ@`>kYCt@`N1Ia&V4D_`&3-_wWhwLXjUq9&uTT8q z`O>;pxj!8f=5c4ZV?DBnr)lTadLT>C*1Z;^j~~G9vPtJoVm~{KxKpVXEC)0;*q;+6 z|872t8`sMNqN3UMQg-xJACdAKBx(cb4i)IAAQ+}uIzf-_+8W$2eHkZRCkx#p0=3=z z1-8LFV|SU!J7suP%1aEWk;88=(3>YzLrxRLThX1^-_<$ed|2oFg4WLc?;k-uF*-Lt z4?81$LVaM)%V9h1ZVyl8$JoXhZxZ5mCIT>W#2kEzKGB-wk2*fR+gzrbTWE3cMb2lfqt**J~oXuKG!y)o}sqkv^T`<|&W5Bmqf$Zz!%;D{wHI`sPx|RxWjD*!e zX~rzHz9&^WA~|P?t)oKfP@e~S&3ac>@968||1pG$$YJSn=5s(IIUO-t$K?Bd=vdH5 z&-oQLVjO$+gdUG-m)vR>`bIo#?UzPmC5vLI2rpdXU&a;)`( zKyjXop!Ho>`pyr|6v{lsPeC9eLe(Q7$`%8bt4IYfTrzFUzHu`S4?(%yyki(Ql2Lh!KJX>qOh;YsCE!1@h-tmLR*C zO%+qDtQ8%fD|;3Qz*h7QF#TvFKBZm?#FI}PfAq*yl=9iu7Q9(Zq#DnaHKJm=K+ZLjJ|W_fykoc?QvO_Q23%!^elw9_kSUef zF}~6D%i{mQI`8}zpqw`R56WptTUSGC3*$eP(?v?-F_{dAo!6)&XL*uITnKS6m5vZPzuQ@&7l{ekPIM_UR zt6W6OP31mr+b=XU)j!rh!PE0NMb&V^R&QLu333lXqK*DE@_%Yl|J(9xQ`n}1a>gk%&Ejj`;tc}R^lb1}F5j~+dlbl^VO9oF(;VCt`Zf1n9uFaNr4a%Aori?riUJtQE#7hF@VRGY zAq*+C1|u;?<}T(x+`8UIPZ|0j`u(c2TvDkYZzr6MO|M;?!+n2g#q`1k+EfF4=M$hG z`|q}5{@`i&lkY?;{eyKEK;*rY^@NRzzW}?McM{if7?^0G9Z6$}oLxcrc#&vLZ{Z|y z5=pvqb#?W?siJKSxy0ULDQPpjh|j%JxA{uH$NB^>x^pHUd%!g6e7FSjJcxGyZj)Hh zKtq{f<2zn<@fBJ%)y%<47)p(gg9~9TPDH1@1L-y>S`Fc_hwL$w)V5ZKhDoEF0!f8d zq8tR*kPsFUPjVFPw1M=U;P~LB-YR&OnYbQHNNhamRfVThvYdbNw7Q9q6#*zNxpF~J z9C)`mCFoT=x!*FPL`|g}x9in$CI^2blb?UyCHWs z^AB0uJBSwuD5m*=p9Lg|hHRyc1ds$eihN75Dp^x>kwc-bPQV#y>`ApY~vodn+k zjdm@tU>WfUdK#_bI9mCoXqkx{(s)r>8l$tPr3NQFu--i2Vbpk%hAN$sm^_$e%>I4; zB$E{tD){wPrh{ZS8;$P#z3Ub#+`#lPL7%P3aNYcB&wFLC48DWh$Ft$GnDdNuqA%=D zGyGiKFk7%QV2jnFc))1kNOJIEz(L#v&6M4p*uWT^lWBr*raiDP26r7s)M-R>GAFnD zTy!lOE1)r6AKbBgjYsW$N|+fGl03+&a(E7r0cN}%(ASD{~2mG_ISi?*(N6k&@s0lkk@bqObEZLd=@ z9W4>V=DGMx>E_xS&PPqOQE$|Hv$)5VF4qaS{hezawl!mX8wK~_`Z$~~1Z-9zpK=UX z?t4Lv`0aKl{X`!`}~y6FF|+xeH1{^_gRD454G zJpkn+0k>Q1-#_jrKk(1LDr@581lSh)FXDmU$NykMFFgJqYv%z^b^kqZBxKK0L@FaY zTlQYrt88(NaE)t=l2BI3-n)!wSlOc}geW6qL?k1!Lim5K=y|Tt_5A+d*X#M+p4ac` zyuass&gXp2=X}N&TcHf4rxt8^zan&zgo5$&6B3RZmdkPJ3hgP_v(pMvI2IQziW!!z zH`dis7})9AdB(2Dq@IeqtWm&Q^o8v?d-i?W%by)yRb6GK50cY7J~2d66&jTZ3(=vt zYjC1DDL9kNQn|N5pOrPMuKhvks*yN2Gd8bmZ7hE-cGWI`hyJ?RI;kChq3#@{VwPsY z}{)N?g^<7v!$b z7uVh!vrl+5ml-^MUp+Zbz7l-dv8^RFKcI%~oZ#h(47NGf*QsINHA7!1Tvwjn?#hAu z#NsUuwB$&5Wf@N?F?G4lCteiBhBo2&dk|;?vA4Q&9ou{sBMW znh`E;o3jw)V&>w|*vTb!kCDdO*E;xWR%W$JR%aQ8vD(Nv8Cu8G1}ibQR(rKj1<0Up zrE0BZBw;M1T_vnB2=^=#x*5i?iZH$;lf!|HU{8t!*prfTy%w!OT`LhoMuXPk#GAIm z1)85@aqZ-ApwsCW0vA=@1Q+t@C)Q;z1fN~KpVKS%X8- z80GGn8CmC439$#MPB7vxUFt;9zv^>SG}-iuIhMwWdHJK)Py-l8Xv=fnC$G_VbleD# zv{vot*BX7KNpE4cP*dlXTB_S^Pqwx)dw1ii@<+CY(K4B)a_4fM`ypK~UkYL29vPP7 zqFe<#Q)~x5PD+JKwt9;MQvYQ7(S`@DjeAPHJmmkGXUW+mq{#0PbuC{<>G8MmT^}j? zf_^C1SaefM=eNzb5ttXhbLDt`(@@o(a8f10k0*PY2J)>+fu3!&lixKaZ-bQ8A!vRb6Y7!N2l4buh5n>I%8M!KXK9+FBXa z?BDTUykvc91i_#DB)mNB%V8@;Z04?UEMD(LKE_nfl=l1jycE4H=7w@1{8xZei7xpg}JLolbVCyFh*JV*X>{+EIJ zF=_;FQCXOzByNAJBt~u4dtFXL|9Rs2O47zi5IwWF%7s)x>BMAw?xvYc$M%yddC&CH zGxJX~esO7NKSy)ADS~IF4nOF@Md@(4EL=`;xl)z#H!3Iklri~v>oDeWDE-9M)#Mm=n_m!r$9WxpP>nlp98E&&!RU+5)1;YE-|M_$M(v%VTGXf{X>O8wWR&IE zHdc3sR`~PyHMm|h!sX07nYV~Vk>(quWOT*s6p3n|Y>{svJ}R0ItMcn746*Yhk1``H z!{duqr`x$q+KYVsC%9dq=c8S8ar@=EXYCb@7fxw={3x^7b1sT$DU@%_ zNP3~eS!Dw@HC;rpbOfr@#c5mQ;Mpbcp{zKJR!JmJ_2a2SH22GKCrzq}77H(!QW`Un zWQ9C~eTcOd?440x`rzFLINRtYqBL<0sIRIJQ+HiHYeDnjoT9$hxMvoJXP-n zHQDRm_|Kwai+`pKnEJLlJuR?`&3g2jpV4H{9sYpBJ#W5KYS**I;yqBv;JWb2Kt69e zO?K4xDb@Nct$D!2@nIc`)(Wmzp%bd3nL-bij@jR-MWJ|%Q;tiSLQlC?LBhi&AFu$K ziS9kVA~b3}J7t&|D|Dq^;d9k-53*c(A)P!g`2>TyRYmF;xdPHBop#zs1S8ay`_~&Y z4PArEf^*281O`0-ThK?TWcFJ zzHx)*9WgT!oUkic#M6zDV&B!|FVH6HxG-6h$y`lo3{QX25>j9?nNEHVJyf|a>O3mO zLWR%cvMcBAGu?T^om}YG`QfQ7!)t#2chOqO8@{yenT@7S%VJ(e^U1aT@%UHpb7MjS z`E`zkqz}sH8bca3=#=_O$M7P;h;J)_udPthh#03d%VYMD60AK=}Sf(-_ zN0s|^#NnPsp|HYeopc2!j42=m6ilh{{(>Bs} ziB#Yv-P&5IZKg(AhO5U+WoY~SbEth?o>(gj%UCQc_caR(YOB``WHjsgq{R{p0ZTq9 zb7qoH+DzHk+mxZHuDk>n;(StG)?fE;m>W4aUfVD|V?6&>xxT?dp>IuM!n*c*--{{A zi>N%&^X|8-#^mVVp1kHKBK;u9eW*`SBV4_a=!%?FcMwjWh;Fxanl@tS3yc=!?EzuW z6?{$mueX^Y`smizFF|$%CR4vZX$zL9dEnpGwzu;Z!>1f=dP2~o#wRPp+}my%vTDhI zp(Feu{+t?Z)^oq1jYn^vcsTc`1jQyw#p>ndFb9)hW}c6vKMDrX zal*w~=JOrAC);{)>ZTuQjgMLmWjW&D=Dtaj>Z!7KdKtkDt7}vnxJ=zX>iR*)Gor*Q zU-DsQ>_Fy*KnC}^9^cn~E6t5m|3=bMh2l&d`2-OG{_&b4dg^LfxL;_PA<3Av;zG%& z*7|PMm{|(MH;u&5sM!OUl*h=RqQ~#)xV(p5{y~!&aiQJ7u4uV=5p!N!H}T{_eePxe~Ptgy%max|C%+gw0?it-G3 zV{*as(7Nfd&cqkRKhb7h#3gwNQd1bJow_~=fZrwOMfgRm^k8<7p_g=_JPNTAJgG&u|2k(5;n=baO+f+$3*P z_Y8|!X7`@3*_afIRFJ^(;nj#zm!B_)L}BEQ^T~0go67IE5Yci^i>z%Rim4lUu{yrc z?E02MYLu?GC7OtLc-*%5o8Q}tvQp3MA_>=?$M!2Zr!NY6gel{(45qf|r0cjV_uRb~ zk!CZh?SM```|x{;YF-VyT6kKMsk?^6)x{!A(Vsr&3iFKB6++ABQ>N$cd0U@+A(&6} zRf_i*biDm*$zZKGPSx#xQ&Hx}Ki`I})Xxpy=pggSkf?uPuIxW~IL0^Du=Sp{27YQ3 z{o5K1!6|e*#_=jDS*mH?Tl1~BpN2)5Uc?)ww+~PYP~Q!Ue^28TI_Yldsc&sadlHkh z(Xm0eOF@baulLh}K?U@FP|Eu=Y;N|R7?_6x)CPFP*FBuV2dcc&UYxAwHGK3S-7upz z%xS=mvCjS>oAH#XstRA8m-I;snf(X?Rm6_#Zyu zSTMlDUM!kz#NP6byA^9t@zh|cj(^q}*t~tw9mu7*+mR{-ovA+ZZ4yxZLb*GiN2P{3 znR?W%M7w&$CntJiavj}k9BH#`;~uB~sG?&Y7vVAK)%?2r$>{d?+qrb+I5$~`N*GrS zoaINQSb8kD(0`Unv$$!kQ91ckUm6M%igQ`|?WI&vW|zYOE@?d#vVF-T~M7(KXL~h+s5Qy=o<&@t}~6 z=2%PS^6N8J9agL8k8#hgq#3rEu0yyeoNaSb_%YVFIEbEpqRp@MP_nJyqc|VGu*xeI z$@UzE#YDh*o-TU)>e51s(RHl#9n%kIj+kWlXC~lVaSxbI!4Cq$Q>smO1IaM_NKC~T zlk_Jw#;emf;#rZDi=rJYLr>^OO2c02np<1@GiI-R6F|MMaifvy`G?^pv!DHf^c`A} zSe;SgnwdpkaM-N+E>}(A+&p1|B|)eh%%v@tYGv+utLpn@>@!)U_g_mNFQm1%(o{bq z)u)&65`rOcssDl?o}RHO_}BnRQGs;MA{Sp&6>PuQbP$LPsYC^87qB>Me(OF=tau8V0 zJ~inw4Hj%m<5U~M=(M@3bIBc5|3-RqF|YY8Jqp2j>2zBGSIXSSv`;noCP?@^e9G^Y zq5ZtZa;=7%hl65?^eQ>ekynsur!0*zk05MzhpTIW2hwCXzTHRK-225Klrbpgec@v%)jZ zK&Bq@GHV_+{c{-&CG)nvUr)<5cJy2#xIROq?(3ciKkUaAtn~PzL9VO^BWp;#KGXdt z4bFlMGzU$#o=)2*=g34%~?j9ETUA)t0!H)f;S5-On-TI^! z%(ZdCTYd(~W$$6p$D1GudC&ZD%TK($`r2wROzL|k`Mete`7_7S1g$`dD_AKQha}{@ z8{3wJtK04F#ohFKHqr`vAg_Fs%(P5l?DfjiHWNRg*bcUYuxEVZl|)|Jm$QqF^%Y~T zzdnolux~zah~#{4TIxIBF}jPwp_dpgpIew_6`jDmGPU9gOI()g; z_dYaSGX5UG<=-211`^5m**DUR!9Jk<41Rkg>H>`J6nQVJ-Rm&HpwM2GG6iGVuWpvb z-xgCvbq}+A_<5Jk7ysB@pRfQo2+Lhfo6DXQS- z1>48;yoQfUGckC15TTP@!6!&Ddnk^!m_~nNFXSQ( zj=1~eOkR)GvOdAGZc|Oo3oVap#Fxv_#>9t&H-ufAl$PeSCws;X&X$c(Bj)vxi=@L- zAXq*F<+{IKvxV4q;K34MbXK%I@$1A;)-lmLFx%{_mZcHd0k_roMo8V7t4n_{74cg5 z{`hwC#k05J_ZgxhguLeZ-?UJ?staHvdSu9CT-pKbn*H)%%!_^VUmKWpGdCkQGXk*n4>pX)|1WVmUm+VRtjs&e8phwRHq(Gh`-w zm9`!qR_uK_Uj{*@vIc9+wqyii}6aStfBI= zUr3Mf`9B-K(W{u3ewp@b%;n={JT^TYx*0kcu8JITU!0vy zqI2=jE9B}DD$J*Otwy6L5!F8VGs2WhFHAn%FU)E zb4FE5UiZh{0hpFu%z4&~XMNbT9|R)a)5-_tyz_C-M@#5&&>b?aJFNAZrHW}?yY;?^ zyGKe-Fr(x%p-1IlAAIk)U~l?b+ys7H6J=rY_f`Sk$ImvxzDIjzaTTr>KHzQamTZWy z6RYCycuM>e0UTLqmzjxY3-)Pl(c=rhS6#`ePsm zM`DZ{DkeK9HPp;$f0tO^AjX6+D{v^Cwns0wI+fLTe)eL*S<+J(+yLA>bdf+w@C_X&7K#M9WEQ`nC@!vtuLPb{E)Zm=d}xA4<2yz4==i8 zoJm^#5KT-)U549Q&vVR7(Eh8Yr%cYFS+dW=i^RepA^E27_R4Xlh{P48o_z9Jx+NAF z2e_o0r}fcjEQvu+rC)eM7ruj%xVS7+kc2Z$%*mPeek&BVEmhLGR+c@|br?h^%BJ}; zou&n-{hNQdR1wlf72wVIHHxG-D&53TAxMyTZqZ^Ybh6H)@9rmjleRMjPwV`1KL2#! zIbMfXkm^rG@TBR(_q!7=uii%K>luDzJx0wM*%f#)#?$0gTI*DQ?PZ2Y+QYnl7Zb(O z6`n#OEZ*WSMzI%h+hDR}GADc=Q5_yMMjxy}eJ_gHhf4aBt7I{a3p(Y`L?FL-bal2< zU~$%qVhr=au=8sAv87w@cyDx7Pig6_AJ$koEAq`%zEwBp2v5?wq1G`TZZblgWrbN*+SBsX7)aiWkxN_D_V6Y_Z zk)`1=GJ?lg^lr61ZQaL)eq0qXyjnXvp7=s~E;}`QvDhI0Ijy0Gv_qddRtZ(!dfwy5 z0?Z5k5?n56n$inVnRuoQswA_v#u+y*ik;5uV|i-djV@z>JG!1I%TQ1UwL=gxr(Va@&p4>)AR*T4Qao}^qd^-AuY)j zVL>Fguy2tX?_Q z048!vghQnmway_tuQ4?)Y8m5;?r4W%;;QE2q>l!UJ?E z*3>!prxzp*EQSY}bf3v`6yAp4$f5Rm7jH>$^<7-Se;78?K3Y~p4W^N(tr7RtCL z?a!2-hTeH!S<(q`U3)eY6m!@m_>IB+9{MZvrR|JF>2F3Vidgdu*(ly`pu6O7K+&Il z==c^a%^qiZ2hjmW^lHLbmA0jr+17fz^Oy&ORO39feiqlm7LJAChW6(E9Swyn?V>`9 zA5toQ+Gw7R?UE(f;0rsXpD7h^hjVCUqOzIh>Cr_$%Cap3srCiqGZE5f*ce$HM()*XuQANq$tLB3nc!0+J}6V<7iNo#^g7Y zJM5Rz9PpSGvo7VFmS}3LY$4@5Co$fq)*zokH6+hrb@x^UmtXFxPeq~b9byC8VD%;W z;cyLOsV~_b6&G%bIE@FMM=!tn)K8%`zFBg%KHUwvmNBAg0lkwyLxn0(N8WeRR;Hrz zdw}1C=Mn4E3{z&_hhqti&OdvWsHhu~K!ow(Mp8%L(P3@<_Zdv`OJc7*o$OCZx4>*V z)$h(X9B=u4H0Ok$6Q1CNMn3Lm4wkUEhtYHCUoUrH%?JmVi|D>lWF8}AZ7;VSc+4+s z9an)vpxr@T?o7DSp8fga(EA%{I#YbNMRW0U*E4x7mj?RNKX9)K=$g;ZEJK}FXU*Qm zX)u{>=$cc92=~A7iZdWc@o?s@SmpBgag94p*ji<3fjeLMg_2S33BJc}fmgCwH3ssv z+MOm8%c>}rz7QDe=blXEC;E~hcll?zkE#ng2#5Dq-d;`>fBXo;x4)-Q-ghqR1kt*y zhe)dF(@@MuD)gvdU#SZ9V_olBzWkZJ6Kb18Q8gSTZchEBSInaDBW*-R$f8ddZ-Xc6 zTGdgs#U;)-Vb2f&oR;%1lAZ`%{!yS6B1DuU&~?@A#iv&-^IZcU1-{+$pTqZ{VzT=x z7zgF|7~x^g@w!sZN2nNWwS{T@HN zh?LpmCc~*~S1R);_1Xl#lW-(!Vw9&Io^!*`OcRfrkl2Td1w0E!5KF-xKi&O$A$$^MsXS+CeXA zbK9FwrZQsPe3^2%=hVw1&F<#BbOs)?XJ~R)29AH@RBXq5xX?3jZLYZ~Pvz0mQ|v{u zF9Tl2T0@_v=RTc)o@o<1r`SS!9WC1>EtHwbMCfNd9v!w*=&!0DJ#{b^t)=pZGIM(z zDWal2&3VBYKfz(w1^I66wDfKv0)teR*Gti1H3T{2P7aXn9*c98vq^7gKWuPR;bo1f zRE@+}jxR4`wG8FAq>C!!|HO`w!udpo3d_N*udl_(eW}rQJpJs&23ebVsYmtb>6nTX z&t4GO9y-e4gw{lMIY8Ky%lmY)6zdW0L=5`7N8G2mT<^I#h8}k)e4K0QJZ9hZf_U^U zt69hAPi&D9r?EmrlTBE&e6f#v*Or~!kY(eybaDEQ>V)Cx%&Jyz?oZf|`MUWI-BXf_ z`u7cEaB;1Q&tvP$&;&X6V+;j<44b2B%)6BNKKVJGyYKnompW^mq7X%?P6Y>B0gN=( z;bTS*Mm|4N)@rDEi2fy>nahgDJ;}p|@t#8B`2xqb-e>4xuov}G(n>mwSKoaouH7WynPS3h(6SgL4#s;|{| zsI+<2xr%2cmW8TxV=pfl!t)CPC|rIsWL7h8?Afe zq|FLmyFq`_D@>Lt5-lmcA%@Vys7jP^7u#nTc#7XQ;ng0~a&aXup@bgmc2MqGQW6>> z`#yOm`7PCvg!fBwGRtr27W@Q)Ue!54m)?8b?;{JAQObuj2+~)^6iJlan|7UXz-@HF zg}pj9B3{P+WT_X^V0CR+J4M9(W1#y-R$(si?JS%X?&yfj80vmUvtumi7hvR*57U-s zFz$}7mGKF?(uBo*>uPG%4$N;Wcf)_>q3rPN=d#o6#Hx+pR8pS3cBdr6G?nlL{Of&Y znLZjc5OemZNA;r&U!D^$5v1+d9(hTobWRlXS9Z`}c@DPx{IBVMp=KNOtMukqIltgY zzFbCWzn!C--OgB|dWt|>(}}y=B)@L5v~0pI7u4t9O@XgW)8EGxZm=$N3_s!>l`mPV(666mfCOZ?w>u3rnwdpB_0e6ga4`Ng@Y zyUhArOszIv=Ps4T<>a8}8RfwuQs^Kv{mIErbix;4Pz`CVC@k zt)C7<&|w2TqEal?>|^a{Rdw!Pq|a3~KJHzCemKTncaF9Av@7vbjeE2SL>6Y(Uz?

      f7QuJGYaA4vmZjDNyB>cKu>< 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%0DTvef%H2Z+J_aLAJhE#+zl6?+$ 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 j7gVvaDEF8SC) diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index 8713a624dc0..67bd3901e57 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -82,8 +82,8 @@ exports org.checkerframework.checker.fenum.qual; exports org.checkerframework.checker.formatter.qual; exports org.checkerframework.checker.guieffect.qual; - exports org.checkerframework.checker.i18n.qual; exports org.checkerframework.checker.i18nformatter.qual; + exports org.checkerframework.checker.i18n.qual; exports org.checkerframework.checker.index.qual; exports org.checkerframework.checker.initialization.qual; exports org.checkerframework.checker.interning.qual; diff --git a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethods.java b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethods.java index da6ce0f6441..6e2b583e75b 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethods.java +++ b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethods.java @@ -77,7 +77,7 @@ @PostconditionAnnotation(qualifier = CalledMethods.class) public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsIf.java b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsIf.java index 001cf1a8a76..928e3aef489 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsIf.java +++ b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsIf.java @@ -64,7 +64,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsOnException.java b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsOnException.java index f0f0cb43261..632e324305a 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsOnException.java +++ b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsOnException.java @@ -22,8 +22,8 @@ * public void callM(T t) { ... } * * - *

      The callM method promises to always call {@code t.m()} before throwing any kind - * of {@link Exception}. + *

      The {@code callM} method promises to always call {@code t.m()} before throwing any kind of + * {@link Exception}. * *

      Note that {@code EnsuresCalledMethodsOnException} only describes behavior for {@link * Exception} (and by extension {@link RuntimeException}, {@link NullPointerException}, etc.) but @@ -63,7 +63,7 @@ // /** // * Returns the exception types under which the postcondition holds. // * - // * @return the exception types under which the postcondition holds. + // * @return the exception types under which the postcondition holds // */ // Class[] exceptions(); @@ -88,7 +88,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsVarArgs.java b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsVarargs.java similarity index 91% rename from src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsVarArgs.java rename to src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsVarargs.java index 5437acc8f7e..34586c6b1d3 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsVarArgs.java +++ b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsVarargs.java @@ -10,7 +10,7 @@ *

      Consider the following method: * *

      - * @EnsuresCalledMethodsVarArgs("m")
      + * @EnsuresCalledMethodsVarargs("m")
        * public void callMOnAll(S s, T t...) { ... }
        * 
      * @@ -20,7 +20,7 @@ *

      This annotation is not checked. An error will always be issued when it is used. */ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) -public @interface EnsuresCalledMethodsVarArgs { +public @interface EnsuresCalledMethodsVarargs { /** * Returns the methods guaranteed to be invoked on the varargs parameters. diff --git a/src/java.base/share/classes/org/checkerframework/checker/i18nformatter/qual/I18nConversionCategory.java b/src/java.base/share/classes/org/checkerframework/checker/i18nformatter/qual/I18nConversionCategory.java index 6c62f3e33c7..0438bbfdf3c 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/i18nformatter/qual/I18nConversionCategory.java +++ b/src/java.base/share/classes/org/checkerframework/checker/i18nformatter/qual/I18nConversionCategory.java @@ -95,7 +95,7 @@ private static Set arrayToSet(E[] a) { } /** - * Return true if a is a subset of b. + * Returns true if a is a subset of b. * * @return true if a is a subset of b */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/EnsuresLTLengthOf.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/EnsuresLTLengthOf.java index 9e5718dedf6..6903a5e9f93 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/EnsuresLTLengthOf.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/EnsuresLTLengthOf.java @@ -20,9 +20,11 @@ *

        * {@code @EnsuresLTLengthOf(value = "end", targetValue = "array", offset = "#1 - 1")
        *  public void shiftIndex(@NonNegative int x) {
      - *      int newEnd = end - x;
      - *      if (newEnd < 0) throw new RuntimeException();
      - *      end = newEnd;
      + *    int newEnd = end - x;
      + *    if (newEnd < 0) {
      + *      throw new RuntimeException();
      + *    }
      + *    end = newEnd;
        *  }
        * }
        * 
      @@ -97,7 +99,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/EnsuresLTLengthOfIf.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/EnsuresLTLengthOfIf.java index 26872a6dc95..28e3dea8479 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/EnsuresLTLengthOfIf.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/EnsuresLTLengthOfIf.java @@ -107,7 +107,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/IndexFor.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/IndexFor.java index 4bfc213db19..7a8ba273313 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/IndexFor.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/IndexFor.java @@ -19,7 +19,7 @@ * *
      {@code
        * class String {
      - *   char charAt(@IndexFor("this") index) { ... }
      + *   char charAt(@IndexFor("this") int index) { ... }
        * }
        * }
      * diff --git a/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeld.java b/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeld.java index cf00c385a98..f0e6b55bddf 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeld.java +++ b/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeld.java @@ -47,7 +47,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeldIf.java b/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeldIf.java index 6980ec88797..aba6c1b9bfa 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeldIf.java +++ b/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeldIf.java @@ -58,7 +58,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/CreatesMustCallFor.java b/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/CreatesMustCallFor.java index be464575c30..989613f0210 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/CreatesMustCallFor.java +++ b/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/CreatesMustCallFor.java @@ -103,7 +103,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/MustCall.java b/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/MustCall.java index 803d1bed320..2aabea501f1 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/MustCall.java +++ b/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/MustCall.java @@ -13,9 +13,9 @@ * An expression of type {@code @MustCall({"m1", "m2"})} may be obligated to call {@code m1()} * and/or {@code m2()} before it is deallocated, but it is not obligated to call any other methods. * - *

      This annotation is enforced by the Object Construction Checker's {@code -AcheckMustCall} mode. - * It enforces that the methods {@code m1()} and {@code m2()} are called on the annotated expression - * before it is deallocated. + *

      This annotation can be enforced by running the Resource Leak Checker. It enforces that the + * methods {@code m1()} and {@code m2()} are called on the annotated expression before it is + * deallocated. * *

      The subtyping relationship is: * diff --git a/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/MustCallUnknown.java b/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/MustCallUnknown.java index 727a839403b..398051fcdd7 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/MustCallUnknown.java +++ b/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/MustCallUnknown.java @@ -11,9 +11,9 @@ * obligation to call any set (even an infinite set!) of methods. This type contains every object. * This type should rarely be written by a programmer. * - *

      The Object Construction Checker cannot verify that the property represented by this annotation - * is enforced; that is, the Object Construction Checker will always issue a warning when the value - * of an expression with this type might be de-allocated. + *

      The Resource Leak Checker cannot verify that the property represented by this annotation is + * enforced; that is, the Resource Leak Checker will always issue a warning when the value of an + * expression with this type might be de-allocated. * * @checker_framework.manual #must-call-checker Must Call Checker */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/NonEmpty.java b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/NonEmpty.java index d5a7f8c15d5..d11bdf976a2 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/NonEmpty.java +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/NonEmpty.java @@ -8,8 +8,9 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * The {@link java.util.Collection Collection}, {@link java.util.Iterator Iterator}, {@link - * java.lang.Iterable Iterable}, or {@link java.util.Map Map} is definitely non-empty. + * The {@link java.util.Collection Collection}, {@link java.util.Iterator Iterator}, {@link Iterable + * Iterable}, or {@link java.util.Map Map}, or {@link java.util.stream.Stream Stream} is definitely + * non-empty. * * @checker_framework.manual #non-empty-checker Non-Empty Checker */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/UnknownNonEmpty.java b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/UnknownNonEmpty.java index 65900f7fa12..09e0157d138 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/UnknownNonEmpty.java +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/UnknownNonEmpty.java @@ -10,7 +10,8 @@ /** * The {@link java.util.Collection Collection}, {@link java.util.Iterator Iterator}, {@link - * java.lang.Iterable Iterable}, or {@link java.util.Map Map} may or may not be empty. + * java.lang.Iterable Iterable}, {@link java.util.Map Map}, or {@link java.util.stream.Stream + * Stream} may or may not be empty. * * @checker_framework.manual #non-empty-checker Non-Empty Checker */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/optional/qual/EnsuresPresent.java b/src/java.base/share/classes/org/checkerframework/checker/optional/qual/EnsuresPresent.java index 841d4135e0e..8539b7aca7c 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/optional/qual/EnsuresPresent.java +++ b/src/java.base/share/classes/org/checkerframework/checker/optional/qual/EnsuresPresent.java @@ -9,10 +9,10 @@ import org.checkerframework.framework.qual.PostconditionAnnotation; /** - * Indicates that the expression evaluates to a non-empty Optional, if the method terminates + * Indicates that the expression evaluates to a present Optional, if the method terminates * successfully. * - *

      This postcondition annotation is useful for methods that construct a non-empty Optional: + *

      This postcondition annotation is useful for methods that construct a present Optional: * *

      * - *

      When a class is {@code @HasQualifierParameter}, all its subclasses are as well. + *

      When a type is {@code @HasQualifierParameter}, all its subtypes are as well. That is, the + * {@code @HasQualifierParameter} annotation is inherited by subtypes. + * + *

      Written on a package

      * *

      When {@code @HasQualifierParameter} is written on a package, it is equivalent to writing that * annotation on each class in the package or in a sub-package. It can be disabled on a specific diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/InheritedAnnotation.java b/src/java.base/share/classes/org/checkerframework/framework/qual/InheritedAnnotation.java index cd1db57dc26..7f82c0176e0 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/InheritedAnnotation.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/InheritedAnnotation.java @@ -7,8 +7,13 @@ import java.lang.annotation.Target; /** - * A meta-annotation that specifies if a declaration annotation should be inherited. This should not - * be written on type annotations. + * A meta-annotation that specifies that a declaration annotation should be inherited. This should + * not be written on type annotations. Unlike {@link java.lang.annotation.Inherited}, this + * meta-annotation causes the declaration annotation to be inherited even if it is used to annotate + * something other than a class. + * + *

      If an annotation type is meta-annotation with {@link java.lang.annotation.Inherited}, that + * annotation will only be inherited when written on a class. */ @Documented @Retention(RetentionPolicy.RUNTIME) diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/InvisibleQualifier.java b/src/java.base/share/classes/org/checkerframework/framework/qual/InvisibleQualifier.java index 1925dc085d0..148b0c98831 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/InvisibleQualifier.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/InvisibleQualifier.java @@ -7,8 +7,24 @@ import java.lang.annotation.Target; /** - * A meta-annotation indicating that an annotation is a type qualifier that should not be visible in - * output. + * A meta-annotation indicating that an annotation is a type qualifier that should not be shown in + * output. {@code @InvisibleQualifier} should only be written on a qualifier that is also + * meta-annotated with {@code @}{@link DefaultQualifierInHierarchy}. + * + *

      By default, the Checker Framework's error messages show every annotation, including inferred + * and default ones (which far outnumber the ones explicitly written by the programmer). Being + * explicit helps users understand the effective annotations, which the Checker Framework operates + * upon. However, the output can be verbose, and it can show annotations that a user should not + * write. For example, a Format String Checker warning message might contain + * "{@code @UnknownCompilerMessageKey Map<@CompilerMessageKey String, @UnknownCompilerMessageKey + * String>}". + * + *

      When an annotation is meta-annotated with {@code @InvisibleQualifier}, then the Checker + * Framework does not print the given qualifier when printing types. For the above example, the + * Format String Checker prints "{@code Map<@CompilerMessageKey String, String>}". + * + *

      If a user runs the Checker Framework with command-line argument {@code -AprintAllQualifiers}, + * then invisible qualifiers are output. */ @Documented @Retention(RetentionPolicy.RUNTIME) From 46905770ef019c72c072bd6e5fab4661c381d024 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 12 Aug 2025 08:00:23 -0700 Subject: [PATCH 21/82] `@Shrinkable` annotations --- README.md | 4 +- checker-qual.jar | Bin 272438 -> 276061 bytes .../share/classes/java/lang/Iterable.java | 3 +- .../classes/java/util/AbstractCollection.java | 12 ++-- .../share/classes/java/util/AbstractList.java | 17 +++--- .../classes/java/util/AbstractQueue.java | 5 +- .../java/util/AbstractSequentialList.java | 9 ++- .../share/classes/java/util/ArrayDeque.java | 34 ++++++----- .../share/classes/java/util/ArrayList.java | 26 ++++---- .../share/classes/java/util/Collection.java | 14 +++-- .../share/classes/java/util/Collections.java | 25 ++++---- .../share/classes/java/util/Deque.java | 29 +++++---- .../share/classes/java/util/HashSet.java | 3 +- .../share/classes/java/util/Iterator.java | 3 +- .../share/classes/java/util/JumboEnumSet.java | 4 +- .../share/classes/java/util/LinkedList.java | 30 ++++----- .../share/classes/java/util/List.java | 20 +++--- .../share/classes/java/util/NavigableSet.java | 4 +- .../classes/java/util/PriorityQueue.java | 20 +++--- .../share/classes/java/util/Queue.java | 5 +- .../classes/java/util/RegularEnumSet.java | 4 +- .../share/classes/java/util/Set.java | 3 +- .../share/classes/java/util/Stack.java | 4 +- .../share/classes/java/util/TreeSet.java | 17 +++--- .../share/classes/java/util/Vector.java | 34 ++++++----- .../util/concurrent/ArrayBlockingQueue.java | 25 ++++---- .../java/util/concurrent/BlockingDeque.java | 28 +++++---- .../java/util/concurrent/BlockingQueue.java | 8 ++- .../concurrent/ConcurrentLinkedDeque.java | 35 ++++++----- .../concurrent/ConcurrentLinkedQueue.java | 17 +++--- .../concurrent/ConcurrentSkipListSet.java | 20 +++--- .../util/concurrent/CopyOnWriteArrayList.java | 27 +++++---- .../util/concurrent/CopyOnWriteArraySet.java | 4 +- .../java/util/concurrent/DelayQueue.java | 20 +++--- .../util/concurrent/LinkedBlockingDeque.java | 57 +++++++++--------- .../util/concurrent/LinkedBlockingQueue.java | 25 ++++---- .../util/concurrent/LinkedTransferQueue.java | 31 +++++----- .../concurrent/PriorityBlockingQueue.java | 25 ++++---- .../util/concurrent/SynchronousQueue.java | 23 ++++--- .../checker/index/qual/BottomGrowShrink.java | 20 ++++++ .../checker/index/qual/GrowOnly.java | 21 +++++++ .../checker/index/qual/PolyGrowShrink.java | 20 ++++++ .../checker/index/qual/Shrinkable.java | 20 ++++++ .../index/qual/UncheckedShrinkable.java | 28 +++++++++ .../checker/index/qual/UnshrinkableRef.java | 25 ++++++++ 45 files changed, 512 insertions(+), 296 deletions(-) create mode 100644 src/java.base/share/classes/org/checkerframework/checker/index/qual/BottomGrowShrink.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/index/qual/GrowOnly.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/index/qual/PolyGrowShrink.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/index/qual/Shrinkable.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/index/qual/UncheckedShrinkable.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/index/qual/UnshrinkableRef.java diff --git a/README.md b/README.md index dc61c9f42da..c1bef843fce 100644 --- a/README.md +++ b/README.md @@ -133,8 +133,8 @@ jar tf checker-qual.jar | grep '\.java$' | sed 's/\/[^/]*\.java/;/' | sed 's/\// The result of the command will be a list of export lines. Replace the existing export lines present in `src/java.base/share/classes/module-info.java` with the newly-generated list of -exports. If no new packages were added, then there are likely going to be no -changes to the `module-info.java` file. +exports. If no new packages were added, then likely no changes are needed +in the `module-info.java` file. Commit the changes, including the new `checker.jar` file and any new `.java` files in a `qual/` directory. (Both are used, by different parts of the build.) diff --git a/checker-qual.jar b/checker-qual.jar index 95fc72c684b807b5eafb8e575f647f3022ba5374..f2bd53327c138b328cc33e14ea0d7829f0b25269 100644 GIT binary patch delta 10269 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 delta 7210 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 { * * @return an Iterator. */ - @PolyNonEmpty Iterator iterator(@PolyNonEmpty Iterable this); + @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty Iterable this); /** * Performs the given action for each element of the {@code Iterable} diff --git a/src/java.base/share/classes/java/util/AbstractCollection.java b/src/java.base/share/classes/java/util/AbstractCollection.java index b9f991dab08..67c1797c19d 100644 --- a/src/java.base/share/classes/java/util/AbstractCollection.java +++ b/src/java.base/share/classes/java/util/AbstractCollection.java @@ -26,6 +26,8 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; @@ -92,7 +94,7 @@ protected AbstractCollection() { * @return an iterator over the elements contained in this collection */ @SideEffectFree - public abstract @PolyNonEmpty Iterator iterator(@PolyNonEmpty AbstractCollection this); + public abstract @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty AbstractCollection this); @Pure public abstract @NonNegative int size(@GuardSatisfied AbstractCollection this); @@ -292,7 +294,7 @@ public boolean add(@GuardSatisfied AbstractCollection this, E e) { * @throws ClassCastException {@inheritDoc} * @throws NullPointerException {@inheritDoc} */ - public boolean remove(@GuardSatisfied AbstractCollection this, @GuardSatisfied @UnknownSignedness Object o) { + public boolean remove(@GuardSatisfied @Shrinkable AbstractCollection this, @GuardSatisfied @UnknownSignedness Object o) { Iterator it = iterator(); if (o==null) { while (it.hasNext()) { @@ -385,7 +387,7 @@ public boolean addAll(@GuardSatisfied AbstractCollection this, Collection this, Collection c) { + public boolean removeAll(@GuardSatisfied @Shrinkable AbstractCollection this, Collection c) { Objects.requireNonNull(c); boolean modified = false; Iterator it = iterator(); @@ -420,7 +422,7 @@ public boolean removeAll(@GuardSatisfied AbstractCollection this, Collection< * @see #remove(Object) * @see #contains(Object) */ - public boolean retainAll(@GuardSatisfied AbstractCollection this, Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable AbstractCollection this, Collection c) { Objects.requireNonNull(c); boolean modified = false; Iterator it = iterator(); @@ -449,7 +451,7 @@ public boolean retainAll(@GuardSatisfied AbstractCollection this, Collection< * * @throws UnsupportedOperationException {@inheritDoc} */ - public void clear(@GuardSatisfied AbstractCollection this) { + public void clear(@GuardSatisfied @Shrinkable AbstractCollection this) { Iterator it = iterator(); while (it.hasNext()) { it.next(); diff --git a/src/java.base/share/classes/java/util/AbstractList.java b/src/java.base/share/classes/java/util/AbstractList.java index a16d1a1db3b..e9365cb857b 100644 --- a/src/java.base/share/classes/java/util/AbstractList.java +++ b/src/java.base/share/classes/java/util/AbstractList.java @@ -28,10 +28,13 @@ import org.checkerframework.checker.index.qual.GTENegativeOne; import org.checkerframework.checker.index.qual.IndexFor; import org.checkerframework.checker.index.qual.IndexOrHigh; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; @@ -183,7 +186,7 @@ public void add(@GuardSatisfied AbstractList this, @IndexOrHigh({"this"}) int * @throws UnsupportedOperationException {@inheritDoc} * @throws IndexOutOfBoundsException {@inheritDoc} */ - public E remove(@GuardSatisfied AbstractList this, @IndexFor({"this"}) int index) { + public E remove(@GuardSatisfied @Shrinkable AbstractList this, @IndexFor({"this"}) int index) { throw new UnsupportedOperationException(); } @@ -261,7 +264,7 @@ public E remove(@GuardSatisfied AbstractList this, @IndexFor({"this"}) int in * @throws UnsupportedOperationException if the {@code clear} operation * is not supported by this list */ - public void clear(@GuardSatisfied AbstractList this) { + public void clear(@GuardSatisfied @Shrinkable AbstractList this) { removeRange(0, size()); } @@ -318,7 +321,7 @@ public boolean addAll(@GuardSatisfied AbstractList this, @IndexOrHigh({"this" * @return an iterator over the elements in this list in proper sequence */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty AbstractList this) { return new Itr(); } @@ -330,7 +333,7 @@ public Iterator iterator() { * * @see #listIterator(int) */ - public ListIterator listIterator() { + public @PolyGrowShrink @PolyNonEmpty ListIterator listIterator(@PolyGrowShrink @PolyNonEmpty AbstractList this) { return listIterator(0); } @@ -357,7 +360,7 @@ public ListIterator listIterator() { * * @throws IndexOutOfBoundsException {@inheritDoc} */ - public ListIterator listIterator(final @IndexOrHigh({"this"}) int index) { + public @PolyGrowShrink ListIterator listIterator(@PolyGrowShrink AbstractList this, final @IndexOrHigh({"this"}) int index) { rangeCheckForAdd(index); return new ListItr(index); @@ -520,7 +523,7 @@ public void add(E e) { * {@code (fromIndex > toIndex)} */ @SideEffectFree - public List subList(@GuardSatisfied AbstractList this, @IndexOrHigh({"this"}) int fromIndex, @IndexOrHigh({"this"}) int toIndex) { + public @PolyGrowShrink List subList(@GuardSatisfied @PolyGrowShrink AbstractList this, @IndexOrHigh({"this"}) int fromIndex, @IndexOrHigh({"this"}) int toIndex) { subListRangeCheck(fromIndex, toIndex, size()); return (this instanceof RandomAccess ? new RandomAccessSubList<>(this, fromIndex, toIndex) : @@ -620,7 +623,7 @@ public int hashCode(@GuardSatisfied AbstractList this) { * @param fromIndex index of first element to be removed * @param toIndex index after last element to be removed */ - protected void removeRange(@IndexOrHigh({"this"}) int fromIndex, @IndexOrHigh({"this"}) int toIndex) { + protected void removeRange(@GuardSatisfied @Shrinkable AbstractList this, @IndexOrHigh({"this"}) int fromIndex, @IndexOrHigh({"this"}) int toIndex) { ListIterator it = listIterator(fromIndex); for (int i=0, n=toIndex-fromIndex; i this, E e) { * @return the head of this queue * @throws NoSuchElementException if this queue is empty */ - public E remove(@GuardSatisfied @NonEmpty AbstractQueue this) { + public E remove(@GuardSatisfied @NonEmpty @Shrinkable AbstractQueue this) { E x = poll(); if (x != null) return x; @@ -150,7 +151,7 @@ public E element(@GuardSatisfied @NonEmpty AbstractQueue this) { *

      This implementation repeatedly invokes {@link #poll poll} until it * returns {@code null}. */ - public void clear(@GuardSatisfied AbstractQueue this) { + public void clear(@GuardSatisfied @Shrinkable AbstractQueue this) { while (poll() != null) ; } diff --git a/src/java.base/share/classes/java/util/AbstractSequentialList.java b/src/java.base/share/classes/java/util/AbstractSequentialList.java index 0d1a3b37544..054a8a463fe 100644 --- a/src/java.base/share/classes/java/util/AbstractSequentialList.java +++ b/src/java.base/share/classes/java/util/AbstractSequentialList.java @@ -25,7 +25,10 @@ package java.util; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -175,7 +178,7 @@ public void add(@GuardSatisfied AbstractSequentialList this, int index, E ele * @throws UnsupportedOperationException {@inheritDoc} * @throws IndexOutOfBoundsException {@inheritDoc} */ - public E remove(@GuardSatisfied AbstractSequentialList this, int index) { + public E remove(@GuardSatisfied @Shrinkable AbstractSequentialList this, int index) { try { ListIterator e = listIterator(index); E outCast = e.next(); @@ -244,7 +247,7 @@ public boolean addAll(@GuardSatisfied AbstractSequentialList this, int index, * @return an iterator over the elements in this list (in proper sequence) */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty AbstractSequentialList this) { return listIterator(); } @@ -258,5 +261,5 @@ public Iterator iterator() { * sequence) * @throws IndexOutOfBoundsException {@inheritDoc} */ - public abstract ListIterator listIterator(int index); + public abstract @PolyGrowShrink ListIterator listIterator(@PolyGrowShrink AbstractSequentialList this, int index); } diff --git a/src/java.base/share/classes/java/util/ArrayDeque.java b/src/java.base/share/classes/java/util/ArrayDeque.java index 75d6541dbd7..97c52c31325 100644 --- a/src/java.base/share/classes/java/util/ArrayDeque.java +++ b/src/java.base/share/classes/java/util/ArrayDeque.java @@ -35,6 +35,8 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -375,7 +377,7 @@ public boolean offerLast(E e) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeFirst(@GuardSatisfied @NonEmpty ArrayDeque this) { + public E removeFirst(@GuardSatisfied @NonEmpty @Shrinkable ArrayDeque this) { E e = pollFirst(); if (e == null) throw new NoSuchElementException(); @@ -385,14 +387,14 @@ public E removeFirst(@GuardSatisfied @NonEmpty ArrayDeque this) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeLast(@GuardSatisfied @NonEmpty ArrayDeque this) { + public E removeLast(@GuardSatisfied @NonEmpty @Shrinkable ArrayDeque this) { E e = pollLast(); if (e == null) throw new NoSuchElementException(); return e; } - public @Nullable E pollFirst(@GuardSatisfied ArrayDeque this) { + public @Nullable E pollFirst(@GuardSatisfied @Shrinkable ArrayDeque this) { final Object[] es; final int h; E e = elementAt(es = elements, h = head); @@ -403,7 +405,7 @@ public E removeLast(@GuardSatisfied @NonEmpty ArrayDeque this) { return e; } - public @Nullable E pollLast(@GuardSatisfied ArrayDeque this) { + public @Nullable E pollLast(@GuardSatisfied @Shrinkable ArrayDeque this) { final Object[] es; final int t; E e = elementAt(es = elements, t = dec(tail, es.length)); @@ -456,7 +458,7 @@ public E getLast(@GuardSatisfied @NonEmpty ArrayDeque this) { * @param o element to be removed from this deque, if present * @return {@code true} if the deque contained the specified element */ - public boolean removeFirstOccurrence(@GuardSatisfied ArrayDeque this, @Nullable Object o) { + public boolean removeFirstOccurrence(@GuardSatisfied @Shrinkable ArrayDeque this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o != null) { final Object[] es = elements; for (int i = head, end = tail, to = (i <= end) ? end : es.length; @@ -484,7 +486,7 @@ public boolean removeFirstOccurrence(@GuardSatisfied ArrayDeque this, @Nullab * @param o element to be removed from this deque, if present * @return {@code true} if the deque contained the specified element */ - public boolean removeLastOccurrence(@GuardSatisfied ArrayDeque this, @Nullable Object o) { + public boolean removeLastOccurrence(@GuardSatisfied @Shrinkable ArrayDeque this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o != null) { final Object[] es = elements; for (int i = tail, end = head, to = (i >= end) ? end : 0; @@ -541,7 +543,7 @@ public boolean offer(@GuardSatisfied ArrayDeque this, E e) { * @return the head of the queue represented by this deque * @throws NoSuchElementException {@inheritDoc} */ - public E remove(@GuardSatisfied @NonEmpty ArrayDeque this) { + public E remove(@GuardSatisfied @NonEmpty @Shrinkable ArrayDeque this) { return removeFirst(); } @@ -555,7 +557,7 @@ public E remove(@GuardSatisfied @NonEmpty ArrayDeque this) { * @return the head of the queue represented by this deque, or * {@code null} if this deque is empty */ - public @Nullable E poll(@GuardSatisfied ArrayDeque this) { + public @Nullable E poll(@GuardSatisfied @Shrinkable ArrayDeque this) { return pollFirst(); } @@ -612,7 +614,7 @@ public void push(@GuardSatisfied ArrayDeque this, E e) { * of the stack represented by this deque) * @throws NoSuchElementException {@inheritDoc} */ - public E pop(@GuardSatisfied @NonEmpty ArrayDeque this) { + public E pop(@GuardSatisfied @NonEmpty @Shrinkable ArrayDeque this) { return removeFirst(); } @@ -694,11 +696,11 @@ public boolean isEmpty(@GuardSatisfied ArrayDeque this) { * @return an iterator over the elements in this deque */ @SideEffectFree - public @PolyNonEmpty Iterator iterator(@PolyNonEmpty ArrayDeque this) { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty ArrayDeque this) { return new DeqIterator(); } - public @PolyNonEmpty Iterator descendingIterator(@PolyNonEmpty ArrayDeque this) { + public @PolyGrowShrink @PolyNonEmpty Iterator descendingIterator(@PolyGrowShrink @PolyNonEmpty ArrayDeque this) { return new DescendingIterator(); } @@ -927,7 +929,7 @@ public void forEach(Consumer action) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable ArrayDeque this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -935,7 +937,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable ArrayDeque this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -943,7 +945,7 @@ public boolean removeAll(Collection c) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean retainAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable ArrayDeque this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } @@ -1059,7 +1061,7 @@ public boolean contains(@GuardSatisfied ArrayDeque this, @GuardSatisfied @Nul * @param o element to be removed from this deque, if present * @return {@code true} if this deque contained the specified element */ - public boolean remove(@GuardSatisfied ArrayDeque this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@GuardSatisfied @Shrinkable ArrayDeque this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { return removeFirstOccurrence(o); } @@ -1067,7 +1069,7 @@ public boolean remove(@GuardSatisfied ArrayDeque this, @GuardSatisfied @Nulla * Removes all of the elements from this deque. * The deque will be empty after this call returns. */ - public void clear(@GuardSatisfied ArrayDeque this) { + public void clear(@GuardSatisfied @Shrinkable ArrayDeque this) { circularClear(elements, head, tail); head = tail = 0; } diff --git a/src/java.base/share/classes/java/util/ArrayList.java b/src/java.base/share/classes/java/util/ArrayList.java index b3a761c4302..fe87ea029a4 100644 --- a/src/java.base/share/classes/java/util/ArrayList.java +++ b/src/java.base/share/classes/java/util/ArrayList.java @@ -27,6 +27,8 @@ import org.checkerframework.checker.index.qual.GTENegativeOne; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -540,7 +542,7 @@ public void add(@GuardSatisfied ArrayList this, @NonNegative int index, E ele * @return the element that was removed from the list * @throws IndexOutOfBoundsException {@inheritDoc} */ - public E remove(@GuardSatisfied ArrayList this, @NonNegative int index) { + public E remove(@GuardSatisfied @Shrinkable ArrayList this, @NonNegative int index) { Objects.checkIndex(index, size); final Object[] es = elementData; @@ -652,7 +654,7 @@ int hashCodeRange(int from, int to) { * @param o element to be removed from this list, if present * @return {@code true} if this list contained the specified element */ - public boolean remove(@GuardSatisfied ArrayList this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@GuardSatisfied @Shrinkable ArrayList this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { final Object[] es = elementData; final int size = this.size; int i = 0; @@ -688,7 +690,7 @@ private void fastRemove(Object[] es, int i) { * Removes all of the elements from this list. The list will * be empty after this call returns. */ - public void clear(@GuardSatisfied ArrayList this) { + public void clear(@GuardSatisfied @Shrinkable ArrayList this) { modCount++; final Object[] es = elementData; for (int to = size, i = size = 0; i < to; i++) @@ -776,7 +778,7 @@ public boolean addAll(@GuardSatisfied ArrayList this, @NonNegative int index, * toIndex > size() || * toIndex < fromIndex}) */ - protected void removeRange(int fromIndex, int toIndex) { + protected void removeRange(@GuardSatisfied @Shrinkable ArrayList this, int fromIndex, int toIndex) { if (fromIndex > toIndex) { throw new IndexOutOfBoundsException( outOfBoundsMsg(fromIndex, toIndex)); @@ -831,7 +833,7 @@ private static String outOfBoundsMsg(int fromIndex, int toIndex) { * or if the specified collection is null * @see Collection#contains(Object) */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable ArrayList this, Collection c) { return batchRemove(c, false, 0, size); } @@ -851,7 +853,7 @@ public boolean removeAll(Collection c) { * or if the specified collection is null * @see Collection#contains(Object) */ - public boolean retainAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable ArrayList this, Collection c) { return batchRemove(c, true, 0, size); } @@ -963,7 +965,7 @@ private void readObject(java.io.ObjectInputStream s) * * @throws IndexOutOfBoundsException {@inheritDoc} */ - public ListIterator listIterator(@NonNegative int index) { + public @PolyGrowShrink ListIterator listIterator(@PolyGrowShrink ArrayList this, @NonNegative int index) { rangeCheckForAdd(index); return new ListItr(index); } @@ -976,7 +978,7 @@ public ListIterator listIterator(@NonNegative int index) { * * @see #listIterator(int) */ - public ListIterator listIterator() { + public @PolyGrowShrink @PolyNonEmpty ListIterator listIterator(@PolyGrowShrink @PolyNonEmpty ArrayList this) { return new ListItr(0); } @@ -988,7 +990,7 @@ public ListIterator listIterator() { * @return an iterator over the elements in this list in proper sequence */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty ArrayList this) { return new Itr(); } @@ -1153,7 +1155,7 @@ public void add(E e) { * @throws IndexOutOfBoundsException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public List subList(@NonNegative int fromIndex, @NonNegative int toIndex) { + public @PolyGrowShrink List subList(@GuardSatisfied @PolyGrowShrink ArrayList this, @NonNegative int fromIndex, @NonNegative int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList<>(this, fromIndex, toIndex); } @@ -1713,7 +1715,7 @@ private static boolean isClear(long[] bits, int i) { * @throws NullPointerException {@inheritDoc} */ @Override - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable ArrayList this, Predicate filter) { return removeIf(filter, 0, size); } @@ -1721,7 +1723,7 @@ public boolean removeIf(Predicate filter) { * Removes all elements satisfying the given predicate, from index * i (inclusive) to index end (exclusive). */ - boolean removeIf(Predicate filter, int i, final int end) { + boolean removeIf(@Shrinkable ArrayList this, Predicate filter, int i, final int end) { Objects.requireNonNull(filter); int expectedModCount = modCount; final Object[] es = elementData; diff --git a/src/java.base/share/classes/java/util/Collection.java b/src/java.base/share/classes/java/util/Collection.java index 9d6df88aa1b..8ea7ca4d9ef 100644 --- a/src/java.base/share/classes/java/util/Collection.java +++ b/src/java.base/share/classes/java/util/Collection.java @@ -26,6 +26,8 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -321,7 +323,7 @@ public interface Collection extends Iterable { * @return an {@code Iterator} over the elements in this collection */ @SideEffectFree - @PolyNonEmpty Iterator iterator(@PolyNonEmpty Collection this); + @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty Collection this); /** * Returns an array containing all of the elements in this collection. @@ -503,7 +505,7 @@ default T[] toArray(IntFunction generator) { * @throws UnsupportedOperationException if the {@code remove} operation * is not supported by this collection */ - boolean remove(@GuardSatisfied Collection this, @UnknownSignedness Object o); + boolean remove(@GuardSatisfied @Shrinkable Collection this, @UnknownSignedness Object o); // Bulk Operations @@ -578,7 +580,7 @@ default T[] toArray(IntFunction generator) { * @see #remove(Object) * @see #contains(Object) */ - boolean removeAll(@GuardSatisfied Collection this, Collection c); + boolean removeAll(@GuardSatisfied @Shrinkable Collection this, Collection c); /** * Removes all of the elements of this collection that satisfy the given @@ -602,7 +604,7 @@ default T[] toArray(IntFunction generator) { * supported. * @since 1.8 */ - default boolean removeIf(Predicate filter) { + default boolean removeIf(@Shrinkable Collection this, Predicate filter) { Objects.requireNonNull(filter); boolean removed = false; final Iterator each = iterator(); @@ -637,7 +639,7 @@ default boolean removeIf(Predicate filter) { * @see #remove(Object) * @see #contains(Object) */ - boolean retainAll(@GuardSatisfied Collection this, Collection c); + boolean retainAll(@GuardSatisfied @Shrinkable Collection this, Collection c); /** * Removes all of the elements from this collection (optional operation). @@ -646,7 +648,7 @@ default boolean removeIf(Predicate filter) { * @throws UnsupportedOperationException if the {@code clear} operation * is not supported by this collection */ - void clear(@GuardSatisfied Collection this); + void clear(@GuardSatisfied @Shrinkable Collection this); // Comparison and hashing diff --git a/src/java.base/share/classes/java/util/Collections.java b/src/java.base/share/classes/java/util/Collections.java index bed3d30cbef..67a03e21d3b 100644 --- a/src/java.base/share/classes/java/util/Collections.java +++ b/src/java.base/share/classes/java/util/Collections.java @@ -27,6 +27,7 @@ import org.checkerframework.checker.index.qual.GTENegativeOne; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -1050,7 +1051,7 @@ public static boolean replaceAll(List list, @Nullable T oldVal, T newVal) */ @SuppressWarnings("unchecked") @SideEffectFree - public static @PolyNonEmpty Collection unmodifiableCollection(@PolyNonEmpty Collection c) { + public static @PolyGrowShrink @PolyNonEmpty Collection unmodifiableCollection(@PolyGrowShrink @PolyNonEmpty Collection c) { if (c.getClass() == UnmodifiableCollection.class) { return (Collection) c; } @@ -1089,7 +1090,7 @@ static class UnmodifiableCollection implements Collection, Serializable { public String toString() {return c.toString();} @SideEffectFree - public @PolyNonEmpty Iterator iterator(@PolyNonEmpty UnmodifiableCollection this) { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty UnmodifiableCollection this) { return new Iterator() { private final Iterator i = c.iterator(); @@ -1366,7 +1367,7 @@ public NavigableSet tailSet(E fromElement, boolean inclusive) { * @return an unmodifiable view of the specified list. */ @SuppressWarnings("unchecked") - public static @PolyNonEmpty List unmodifiableList(@PolyNonEmpty List list) { + public static @PolyGrowShrink @PolyNonEmpty List unmodifiableList(@PolyGrowShrink @PolyNonEmpty List list) { if (list.getClass() == UnmodifiableList.class || list.getClass() == UnmodifiableRandomAccessList.class) { return (List) list; } @@ -1420,7 +1421,7 @@ public void sort(Comparator c) { throw new UnsupportedOperationException(); } - public @PolyNonEmpty ListIterator listIterator(@PolyNonEmpty UnmodifiableList this) {return listIterator(0);} + public @PolyGrowShrink @PolyNonEmpty ListIterator listIterator(@PolyGrowShrink @PolyNonEmpty UnmodifiableList this) {return listIterator(0);} public ListIterator listIterator(final int index) { return new ListIterator() { @@ -2128,11 +2129,11 @@ public NavigableMap tailMap(K fromKey, boolean inclusive) * @param c the collection to be "wrapped" in a synchronized collection. * @return a synchronized view of the specified collection. */ - public static Collection synchronizedCollection(Collection c) { + public static @PolyGrowShrink @PolyNonEmpty Collection synchronizedCollection(@PolyGrowShrink @PolyNonEmpty Collection c) { return new SynchronizedCollection<>(c); } - static Collection synchronizedCollection(Collection c, Object mutex) { + static @PolyGrowShrink @PolyNonEmpty Collection synchronizedCollection(@PolyGrowShrink @PolyNonEmpty Collection c, Object mutex) { return new SynchronizedCollection<>(c, mutex); } @@ -2544,13 +2545,13 @@ public NavigableSet tailSet(E fromElement, boolean inclusive) { * @param list the list to be "wrapped" in a synchronized list. * @return a synchronized view of the specified list. */ - public static List synchronizedList(List list) { + public static @PolyGrowShrink @PolyNonEmpty List synchronizedList(@PolyGrowShrink @PolyNonEmpty List list) { return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<>(list) : new SynchronizedList<>(list)); } - static List synchronizedList(List list, Object mutex) { + static @PolyGrowShrink @PolyNonEmpty List synchronizedList(@PolyGrowShrink @PolyNonEmpty List list, Object mutex) { return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<>(list, mutex) : new SynchronizedList<>(list, mutex)); @@ -3221,7 +3222,7 @@ public NavigableMap tailMap(K fromKey, boolean inclusive) { * @return a dynamically typesafe view of the specified collection * @since 1.5 */ - public static Collection checkedCollection(Collection c, + public static @PolyGrowShrink @PolyNonEmpty Collection checkedCollection(@PolyGrowShrink @PolyNonEmpty Collection c, Class type) { return new CheckedCollection<>(c, type); } @@ -3391,7 +3392,7 @@ public boolean removeIf(Predicate filter) { * @return a dynamically typesafe view of the specified queue * @since 1.8 */ - public static Queue checkedQueue(Queue queue, Class type) { + public static @PolyGrowShrink @PolyNonEmpty Queue checkedQueue(@PolyGrowShrink @PolyNonEmpty Queue queue, Class type) { return new CheckedQueue<>(queue, type); } @@ -3646,7 +3647,7 @@ public NavigableSet tailSet(E fromElement, boolean inclusive) { * @return a dynamically typesafe view of the specified list * @since 1.5 */ - public static List checkedList(List list, Class type) { + public static @PolyGrowShrink @PolyNonEmpty List checkedList(@PolyGrowShrink @PolyNonEmpty List list, Class type) { return (list instanceof RandomAccess ? new CheckedRandomAccessList<>(list, type) : new CheckedList<>(list, type)); @@ -5992,7 +5993,7 @@ private void readObject(java.io.ObjectInputStream stream) * @return the queue * @since 1.6 */ - public static Queue asLifoQueue(Deque deque) { + public static @PolyGrowShrink @PolyNonEmpty Queue asLifoQueue(@PolyGrowShrink @PolyNonEmpty Deque deque) { return new AsLIFOQueue<>(Objects.requireNonNull(deque)); } diff --git a/src/java.base/share/classes/java/util/Deque.java b/src/java.base/share/classes/java/util/Deque.java index c538662e94b..980ea5ce43b 100644 --- a/src/java.base/share/classes/java/util/Deque.java +++ b/src/java.base/share/classes/java/util/Deque.java @@ -36,10 +36,13 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; @@ -302,7 +305,7 @@ public interface Deque extends Queue { * @return the head of this deque * @throws NoSuchElementException if this deque is empty */ - E removeFirst(@GuardSatisfied @NonEmpty Deque this); + E removeFirst(@GuardSatisfied @NonEmpty @Shrinkable Deque this); /** * Retrieves and removes the last element of this deque. This method @@ -312,7 +315,7 @@ public interface Deque extends Queue { * @return the tail of this deque * @throws NoSuchElementException if this deque is empty */ - E removeLast(@GuardSatisfied @NonEmpty Deque this); + E removeLast(@GuardSatisfied @NonEmpty @Shrinkable Deque this); /** * Retrieves and removes the first element of this deque, @@ -320,7 +323,7 @@ public interface Deque extends Queue { * * @return the head of this deque, or {@code null} if this deque is empty */ - @Nullable E pollFirst(@GuardSatisfied Deque this); + @Nullable E pollFirst(@GuardSatisfied @Shrinkable Deque this); /** * Retrieves and removes the last element of this deque, @@ -328,7 +331,7 @@ public interface Deque extends Queue { * * @return the tail of this deque, or {@code null} if this deque is empty */ - @Nullable E pollLast(@GuardSatisfied Deque this); + @Nullable E pollLast(@GuardSatisfied @Shrinkable Deque this); /** * Retrieves, but does not remove, the first element of this deque. @@ -340,7 +343,7 @@ public interface Deque extends Queue { * @throws NoSuchElementException if this deque is empty */ @EnsuresNonEmpty("this") - E getFirst(@GuardSatisfied @NonEmpty Deque this); + E getFirst(@GuardSatisfied @NonEmpty @Shrinkable Deque this); /** * Retrieves, but does not remove, the last element of this deque. @@ -351,7 +354,7 @@ public interface Deque extends Queue { * @throws NoSuchElementException if this deque is empty */ @EnsuresNonEmpty("this") - E getLast(@GuardSatisfied @NonEmpty Deque this); + E getLast(@GuardSatisfied @NonEmpty @Shrinkable Deque this); /** * Retrieves, but does not remove, the first element of this deque, @@ -386,7 +389,7 @@ public interface Deque extends Queue { * deque does not permit null elements * (optional) */ - boolean removeFirstOccurrence(@GuardSatisfied Deque this, Object o); + boolean removeFirstOccurrence(@GuardSatisfied @Shrinkable Deque this, Object o); /** * Removes the last occurrence of the specified element from this deque. @@ -405,7 +408,7 @@ public interface Deque extends Queue { * deque does not permit null elements * (optional) */ - boolean removeLastOccurrence(@GuardSatisfied Deque this, Object o); + boolean removeLastOccurrence(@GuardSatisfied @Shrinkable Deque this, Object o); // *** Queue methods *** @@ -468,7 +471,7 @@ public interface Deque extends Queue { * @return the head of the queue represented by this deque * @throws NoSuchElementException if this deque is empty */ - E remove(@GuardSatisfied @NonEmpty Deque this); + E remove(@GuardSatisfied @NonEmpty @Shrinkable Deque this); /** * Retrieves and removes the head of the queue represented by this deque @@ -480,7 +483,7 @@ public interface Deque extends Queue { * @return the first element of this deque, or {@code null} if * this deque is empty */ - @Nullable E poll(@GuardSatisfied Deque this); + @Nullable E poll(@GuardSatisfied @Shrinkable Deque this); /** * Retrieves, but does not remove, the head of the queue represented by @@ -565,7 +568,7 @@ public interface Deque extends Queue { * of the stack represented by this deque) * @throws NoSuchElementException if this deque is empty */ - E pop(@GuardSatisfied @NonEmpty Deque this); + E pop(@GuardSatisfied @NonEmpty @Shrinkable Deque this); // *** Collection methods *** @@ -589,7 +592,7 @@ public interface Deque extends Queue { * deque does not permit null elements * (optional) */ - boolean remove(@GuardSatisfied Deque this, @UnknownSignedness Object o); + boolean remove(@GuardSatisfied @Shrinkable Deque this, @UnknownSignedness Object o); /** * Returns {@code true} if this deque contains the specified element. @@ -624,7 +627,7 @@ public interface Deque extends Queue { * @return an iterator over the elements in this deque in proper sequence */ @SideEffectFree - Iterator iterator(); + @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty Deque this); /** * Returns an iterator over the elements in this deque in reverse diff --git a/src/java.base/share/classes/java/util/HashSet.java b/src/java.base/share/classes/java/util/HashSet.java index 98d02eb218c..44120107618 100644 --- a/src/java.base/share/classes/java/util/HashSet.java +++ b/src/java.base/share/classes/java/util/HashSet.java @@ -26,6 +26,7 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -186,7 +187,7 @@ public HashSet(@NonNegative int initialCapacity) { * @see ConcurrentModificationException */ @SideEffectFree - public @PolyNonEmpty Iterator iterator(@PolyNonEmpty HashSet this) { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty HashSet this) { return map.keySet().iterator(); } diff --git a/src/java.base/share/classes/java/util/Iterator.java b/src/java.base/share/classes/java/util/Iterator.java index 873f17166e9..fb353dbdc2e 100644 --- a/src/java.base/share/classes/java/util/Iterator.java +++ b/src/java.base/share/classes/java/util/Iterator.java @@ -25,6 +25,7 @@ package java.util; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; @@ -115,7 +116,7 @@ public interface Iterator { * been called after the last call to the {@code next} * method */ - default void remove(@GuardSatisfied Iterator this) { + default void remove(@GuardSatisfied @Shrinkable Iterator this) { throw new UnsupportedOperationException("remove"); } diff --git a/src/java.base/share/classes/java/util/JumboEnumSet.java b/src/java.base/share/classes/java/util/JumboEnumSet.java index 5ea2c67f19e..c84521c7057 100644 --- a/src/java.base/share/classes/java/util/JumboEnumSet.java +++ b/src/java.base/share/classes/java/util/JumboEnumSet.java @@ -25,10 +25,12 @@ package java.util; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -108,7 +110,7 @@ void complement() { * * @return an iterator over the elements contained in this set */ - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty JumboEnumSet this) { return new EnumSetIterator<>(); } diff --git a/src/java.base/share/classes/java/util/LinkedList.java b/src/java.base/share/classes/java/util/LinkedList.java index 976ba956783..1cea55d756b 100644 --- a/src/java.base/share/classes/java/util/LinkedList.java +++ b/src/java.base/share/classes/java/util/LinkedList.java @@ -27,6 +27,8 @@ import org.checkerframework.checker.index.qual.GTENegativeOne; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.lock.qual.ReleasesNoLocks; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; @@ -288,7 +290,7 @@ public E getLast(@GuardSatisfied @NonEmpty LinkedList this) { * @return the first element from this list * @throws NoSuchElementException if this list is empty */ - public E removeFirst(@GuardSatisfied @NonEmpty LinkedList this) { + public E removeFirst(@GuardSatisfied @NonEmpty @Shrinkable LinkedList this) { final Node f = first; if (f == null) throw new NoSuchElementException(); @@ -301,7 +303,7 @@ public E removeFirst(@GuardSatisfied @NonEmpty LinkedList this) { * @return the last element from this list * @throws NoSuchElementException if this list is empty */ - public E removeLast(@GuardSatisfied @NonEmpty LinkedList this) { + public E removeLast(@GuardSatisfied @NonEmpty @Shrinkable LinkedList this) { final Node l = last; if (l == null) throw new NoSuchElementException(); @@ -382,7 +384,7 @@ public boolean add(@GuardSatisfied LinkedList this, E e) { * @return {@code true} if this list contained the specified element */ @ReleasesNoLocks - public boolean remove(@GuardSatisfied LinkedList this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@GuardSatisfied @Shrinkable LinkedList this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o == null) { for (Node x = first; x != null; x = x.next) { if (x.item == null) { @@ -475,7 +477,7 @@ public boolean addAll(@GuardSatisfied LinkedList this, @NonNegative int index * Removes all of the elements from this list. * The list will be empty after this call returns. */ - public void clear(@GuardSatisfied LinkedList this) { + public void clear(@GuardSatisfied @Shrinkable LinkedList this) { // Clearing all of the links between nodes is "unnecessary", but: // - helps a generational GC if the discarded nodes inhabit // more than one generation @@ -552,7 +554,7 @@ public void add(@GuardSatisfied LinkedList this, @NonNegative int index, E el * @return the element previously at the specified position * @throws IndexOutOfBoundsException {@inheritDoc} */ - public E remove(@GuardSatisfied LinkedList this, @NonNegative int index) { + public E remove(@GuardSatisfied @Shrinkable LinkedList this, @NonNegative int index) { checkElementIndex(index); return unlink(node(index)); } @@ -703,7 +705,7 @@ public E element(@GuardSatisfied @NonEmpty LinkedList this) { * @return the head of this list, or {@code null} if this list is empty * @since 1.5 */ - public @Nullable E poll(@GuardSatisfied LinkedList this) { + public @Nullable E poll(@GuardSatisfied @Shrinkable LinkedList this) { final Node f = first; return (f == null) ? null : unlinkFirst(f); } @@ -715,7 +717,7 @@ public E element(@GuardSatisfied @NonEmpty LinkedList this) { * @throws NoSuchElementException if this list is empty * @since 1.5 */ - public E remove(@GuardSatisfied @NonEmpty LinkedList this) { + public E remove(@GuardSatisfied @NonEmpty @Shrinkable LinkedList this) { return removeFirst(); } @@ -791,7 +793,7 @@ public boolean offerLast(E e) { * this list is empty * @since 1.6 */ - public @Nullable E pollFirst(@GuardSatisfied LinkedList this) { + public @Nullable E pollFirst(@GuardSatisfied @Shrinkable LinkedList this) { final Node f = first; return (f == null) ? null : unlinkFirst(f); } @@ -804,7 +806,7 @@ public boolean offerLast(E e) { * this list is empty * @since 1.6 */ - public @Nullable E pollLast(@GuardSatisfied LinkedList this) { + public @Nullable E pollLast(@GuardSatisfied @Shrinkable LinkedList this) { final Node l = last; return (l == null) ? null : unlinkLast(l); } @@ -833,7 +835,7 @@ public void push(@GuardSatisfied LinkedList this, E e) { * @throws NoSuchElementException if this list is empty * @since 1.6 */ - public E pop(@GuardSatisfied @NonEmpty LinkedList this) { + public E pop(@GuardSatisfied @NonEmpty @Shrinkable LinkedList this) { return removeFirst(); } @@ -846,7 +848,7 @@ public E pop(@GuardSatisfied @NonEmpty LinkedList this) { * @return {@code true} if the list contained the specified element * @since 1.6 */ - public boolean removeFirstOccurrence(@GuardSatisfied LinkedList this, @Nullable Object o) { + public boolean removeFirstOccurrence(@GuardSatisfied @Shrinkable LinkedList this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { return remove(o); } @@ -859,7 +861,7 @@ public boolean removeFirstOccurrence(@GuardSatisfied LinkedList this, @Nullab * @return {@code true} if the list contained the specified element * @since 1.6 */ - public boolean removeLastOccurrence(@GuardSatisfied LinkedList this, @Nullable Object o) { + public boolean removeLastOccurrence(@GuardSatisfied @Shrinkable LinkedList this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o == null) { for (Node x = last; x != null; x = x.prev) { if (x.item == null) { @@ -899,7 +901,7 @@ public boolean removeLastOccurrence(@GuardSatisfied LinkedList this, @Nullabl * @throws IndexOutOfBoundsException {@inheritDoc} * @see List#listIterator(int) */ - public ListIterator listIterator(@NonNegative int index) { + public @PolyGrowShrink @PolyNonEmpty ListIterator listIterator(@PolyGrowShrink @PolyNonEmpty LinkedList this, @NonNegative int index) { checkPositionIndex(index); return new ListItr(index); } @@ -1021,7 +1023,7 @@ private static class Node { /** * @since 1.6 */ - public Iterator descendingIterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator descendingIterator(@PolyGrowShrink @PolyNonEmpty LinkedList this) { return new DescendingIterator(); } diff --git a/src/java.base/share/classes/java/util/List.java b/src/java.base/share/classes/java/util/List.java index 99a8bc5f398..600761fb6c6 100644 --- a/src/java.base/share/classes/java/util/List.java +++ b/src/java.base/share/classes/java/util/List.java @@ -29,6 +29,8 @@ import org.checkerframework.checker.index.qual.IndexFor; import org.checkerframework.checker.index.qual.IndexOrHigh; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.lock.qual.ReleasesNoLocks; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; @@ -208,7 +210,7 @@ public interface List extends Collection { * @return an iterator over the elements in this list in proper sequence */ @SideEffectFree - @PolyNonEmpty Iterator iterator(@PolyNonEmpty List this); + @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty List this); /** * Returns an array containing all of the elements in this list in proper @@ -323,7 +325,7 @@ public interface List extends Collection { * is not supported by this list */ @SideEffectsOnly("this") - boolean remove(@GuardSatisfied List this, @UnknownSignedness Object o); + boolean remove(@GuardSatisfied @Shrinkable List this, @UnknownSignedness Object o); // Bulk Modification Operations @@ -423,7 +425,7 @@ public interface List extends Collection { * @see #remove(Object) * @see #contains(Object) */ - boolean removeAll(@GuardSatisfied List this, Collection c); + boolean removeAll(@GuardSatisfied @Shrinkable List this, Collection c); /** * Retains only the elements in this list that are contained in the @@ -445,7 +447,7 @@ public interface List extends Collection { * @see #remove(Object) * @see #contains(Object) */ - boolean retainAll(@GuardSatisfied List this, Collection c); + boolean retainAll(@GuardSatisfied @Shrinkable List this, Collection c); /** * Replaces each element of this list with the result of applying the @@ -561,7 +563,7 @@ default void sort(Comparator c) { * @throws UnsupportedOperationException if the {@code clear} operation * is not supported by this list */ - void clear(@GuardSatisfied List this); + void clear(@GuardSatisfied @Shrinkable List this); // Comparison and hashing @@ -674,7 +676,7 @@ default void sort(Comparator c) { * ({@code index < 0 || index >= size()}) */ @ReleasesNoLocks - E remove(@GuardSatisfied List this, @IndexFor({"this"}) int index); + E remove(@GuardSatisfied @Shrinkable List this, @IndexFor({"this"}) int index); // Search Operations @@ -729,7 +731,7 @@ default void sort(Comparator c) { * @return a list iterator over the elements in this list (in proper * sequence) */ - ListIterator listIterator(); + @PolyGrowShrink @PolyNonEmpty ListIterator listIterator(@PolyGrowShrink @PolyNonEmpty List this); /** * Returns a list iterator over the elements in this list (in proper @@ -746,7 +748,7 @@ default void sort(Comparator c) { * @throws IndexOutOfBoundsException if the index is out of range * ({@code index < 0 || index > size()}) */ - ListIterator listIterator(@IndexOrHigh({"this"}) int index); + @PolyGrowShrink @PolyNonEmpty ListIterator listIterator(@PolyGrowShrink @PolyNonEmpty List this, @IndexOrHigh({"this"}) int index); // View @@ -785,7 +787,7 @@ default void sort(Comparator c) { * fromIndex > toIndex}) */ @SideEffectFree - List subList(@GuardSatisfied List this, @IndexOrHigh({"this"}) int fromIndex, @IndexOrHigh({"this"}) int toIndex); + @PolyGrowShrink List subList(@GuardSatisfied @PolyGrowShrink List this, @IndexOrHigh({"this"}) int fromIndex, @IndexOrHigh({"this"}) int toIndex); /** * Creates a {@link Spliterator} over the elements in this list. diff --git a/src/java.base/share/classes/java/util/NavigableSet.java b/src/java.base/share/classes/java/util/NavigableSet.java index 1f742334eb7..f151aa4a591 100644 --- a/src/java.base/share/classes/java/util/NavigableSet.java +++ b/src/java.base/share/classes/java/util/NavigableSet.java @@ -35,7 +35,9 @@ package java.util; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -174,7 +176,7 @@ public interface NavigableSet extends SortedSet { * @return an iterator over the elements in this set, in ascending order */ @SideEffectFree - Iterator iterator(); + @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty NavigableSet this); /** * Returns a reverse order view of the elements contained in this set. diff --git a/src/java.base/share/classes/java/util/PriorityQueue.java b/src/java.base/share/classes/java/util/PriorityQueue.java index 649c8ff5712..f3b25d1c36e 100644 --- a/src/java.base/share/classes/java/util/PriorityQueue.java +++ b/src/java.base/share/classes/java/util/PriorityQueue.java @@ -26,7 +26,9 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.index.qual.Positive; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -379,7 +381,7 @@ private int indexOf(@GuardSatisfied @Nullable @UnknownSignedness Object o) { * @param o element to be removed from this queue, if present * @return {@code true} if this queue changed as a result of the call */ - public boolean remove(@GuardSatisfied PriorityQueue this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@GuardSatisfied @Shrinkable PriorityQueue this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { int i = indexOf(o); if (i == -1) return false; @@ -394,7 +396,7 @@ public boolean remove(@GuardSatisfied PriorityQueue this, @GuardSatisfied @Nu * * @param o element to be removed from this queue, if present */ - void removeEq(Object o) { + void removeEq(@GuardSatisfied @Shrinkable PriorityQueue this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { final Object[] es = queue; for (int i = 0, n = size; i < n; i++) { if (o == es[i]) { @@ -491,7 +493,7 @@ public boolean contains(@GuardSatisfied PriorityQueue this, @GuardSatisfied @ * @return an iterator over the elements in this queue */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty PriorityQueue this) { return new Itr(); } @@ -591,7 +593,7 @@ public void remove() { * Removes all of the elements from this priority queue. * The queue will be empty after this call returns. */ - public void clear(@GuardSatisfied PriorityQueue this) { + public void clear(@GuardSatisfied @Shrinkable PriorityQueue this) { modCount++; final Object[] es = queue; for (int i = 0, n = size; i < n; i++) @@ -599,7 +601,7 @@ public void clear(@GuardSatisfied PriorityQueue this) { size = 0; } - public @Nullable E poll(@GuardSatisfied PriorityQueue this) { + public @Nullable E poll(@GuardSatisfied @Shrinkable PriorityQueue this) { final Object[] es; final E result; @@ -631,7 +633,7 @@ public void clear(@GuardSatisfied PriorityQueue this) { * position before i. This fact is used by iterator.remove so as to * avoid missing traversing elements. */ - E removeAt(int i) { + E removeAt(@GuardSatisfied @NonEmpty @Shrinkable PriorityQueue this, int i) { // assert i >= 0 && i < size; final Object[] es = queue; modCount++; @@ -922,7 +924,7 @@ public int characteristics() { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@GuardSatisfied @Shrinkable PriorityQueue this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -930,7 +932,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@GuardSatisfied @Shrinkable PriorityQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -938,7 +940,7 @@ public boolean removeAll(Collection c) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean retainAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable PriorityQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } diff --git a/src/java.base/share/classes/java/util/Queue.java b/src/java.base/share/classes/java/util/Queue.java index 0c7343acc26..4b9e5441780 100644 --- a/src/java.base/share/classes/java/util/Queue.java +++ b/src/java.base/share/classes/java/util/Queue.java @@ -35,6 +35,7 @@ package java.util; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -194,7 +195,7 @@ public interface Queue extends Collection { * @return the head of this queue * @throws NoSuchElementException if this queue is empty */ - E remove(@GuardSatisfied @NonEmpty Queue this); + E remove(@GuardSatisfied @NonEmpty @Shrinkable Queue this); /** * Retrieves and removes the head of this queue, @@ -202,7 +203,7 @@ public interface Queue extends Collection { * * @return the head of this queue, or {@code null} if this queue is empty */ - @Nullable E poll(@GuardSatisfied Queue this); + @Nullable E poll(@GuardSatisfied @Shrinkable Queue this); /** * Retrieves, but does not remove, the head of this queue. This method diff --git a/src/java.base/share/classes/java/util/RegularEnumSet.java b/src/java.base/share/classes/java/util/RegularEnumSet.java index 743bde6a03c..a32a65f3a85 100644 --- a/src/java.base/share/classes/java/util/RegularEnumSet.java +++ b/src/java.base/share/classes/java/util/RegularEnumSet.java @@ -26,10 +26,12 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -87,7 +89,7 @@ void complement() { * * @return an iterator over the elements contained in this set */ - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty RegularEnumSet this) { return new EnumSetIterator<>(); } diff --git a/src/java.base/share/classes/java/util/Set.java b/src/java.base/share/classes/java/util/Set.java index 3e3dda8e533..0db338eaaeb 100644 --- a/src/java.base/share/classes/java/util/Set.java +++ b/src/java.base/share/classes/java/util/Set.java @@ -26,6 +26,7 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -178,7 +179,7 @@ public interface Set extends Collection { * @return an iterator over the elements in this set */ @SideEffectFree - @PolyNonEmpty Iterator iterator(@PolyNonEmpty Set this); + @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty Set this); /** * Returns an array containing all of the elements in this set. diff --git a/src/java.base/share/classes/java/util/Stack.java b/src/java.base/share/classes/java/util/Stack.java index 6bb22a593e6..76a14a600ec 100644 --- a/src/java.base/share/classes/java/util/Stack.java +++ b/src/java.base/share/classes/java/util/Stack.java @@ -25,8 +25,10 @@ package java.util; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -85,7 +87,7 @@ public E push(@GuardSatisfied Stack this, E item) { * of the {@code Vector} object). * @throws EmptyStackException if this stack is empty. */ - public synchronized E pop(@GuardSatisfied Stack this) { + public synchronized E pop(@GuardSatisfied @NonEmpty @Shrinkable Stack this) { E obj; int len = size(); diff --git a/src/java.base/share/classes/java/util/TreeSet.java b/src/java.base/share/classes/java/util/TreeSet.java index 1763fbf81de..ce8e1c663d1 100644 --- a/src/java.base/share/classes/java/util/TreeSet.java +++ b/src/java.base/share/classes/java/util/TreeSet.java @@ -26,6 +26,7 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -194,7 +195,7 @@ public TreeSet(@Nullable Comparator comparator) { * @return an iterator over the elements in this set in ascending order */ @SideEffectFree - public @PolyNonEmpty Iterator iterator(@PolyNonEmpty TreeSet this) { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty TreeSet this) { return m.navigableKeySet().iterator(); } @@ -204,7 +205,7 @@ public TreeSet(@Nullable Comparator comparator) { * @return an iterator over the elements in this set in descending order * @since 1.6 */ - public @PolyNonEmpty Iterator descendingIterator(@PolyNonEmpty TreeSet this) { + public @PolyGrowShrink @PolyNonEmpty Iterator descendingIterator(@PolyGrowShrink @PolyNonEmpty TreeSet this) { return m.descendingKeySet().iterator(); } @@ -342,7 +343,7 @@ public boolean addAll(@GuardSatisfied TreeSet this, Collection * @since 1.6 */ @SideEffectFree - public NavigableSet subSet(@GuardSatisfied TreeSet this, @GuardSatisfied E fromElement, boolean fromInclusive, + public @PolyGrowShrink NavigableSet subSet(@GuardSatisfied @PolyGrowShrink TreeSet this, @GuardSatisfied E fromElement, boolean fromInclusive, @GuardSatisfied E toElement, boolean toInclusive) { return new TreeSet<>(m.subMap(fromElement, fromInclusive, toElement, toInclusive)); @@ -357,7 +358,7 @@ public NavigableSet subSet(@GuardSatisfied TreeSet this, @GuardSatisfied E * @since 1.6 */ @SideEffectFree - public NavigableSet headSet(@GuardSatisfied TreeSet this, @GuardSatisfied E toElement, boolean inclusive) { + public @PolyGrowShrink NavigableSet headSet(@GuardSatisfied @PolyGrowShrink TreeSet this, @GuardSatisfied E toElement, boolean inclusive) { return new TreeSet<>(m.headMap(toElement, inclusive)); } @@ -370,7 +371,7 @@ public NavigableSet headSet(@GuardSatisfied TreeSet this, @GuardSatisfied * @since 1.6 */ @SideEffectFree - public NavigableSet tailSet(@GuardSatisfied TreeSet this, @GuardSatisfied E fromElement, boolean inclusive) { + public @PolyGrowShrink NavigableSet tailSet(@GuardSatisfied @PolyGrowShrink TreeSet this, @GuardSatisfied E fromElement, boolean inclusive) { return new TreeSet<>(m.tailMap(fromElement, inclusive)); } @@ -382,7 +383,7 @@ public NavigableSet tailSet(@GuardSatisfied TreeSet this, @GuardSatisfied * @throws IllegalArgumentException {@inheritDoc} */ @SideEffectFree - public SortedSet subSet(@GuardSatisfied TreeSet this, @GuardSatisfied E fromElement, @GuardSatisfied E toElement) { + public @PolyGrowShrink SortedSet subSet(@GuardSatisfied @PolyGrowShrink TreeSet this, @GuardSatisfied E fromElement, @GuardSatisfied E toElement) { return subSet(fromElement, true, toElement, false); } @@ -394,7 +395,7 @@ public SortedSet subSet(@GuardSatisfied TreeSet this, @GuardSatisfied E fr * @throws IllegalArgumentException {@inheritDoc} */ @SideEffectFree - public SortedSet headSet(@GuardSatisfied TreeSet this, E toElement) { + public @PolyGrowShrink SortedSet headSet(@GuardSatisfied @PolyGrowShrink TreeSet this, E toElement) { return headSet(toElement, false); } @@ -406,7 +407,7 @@ public SortedSet headSet(@GuardSatisfied TreeSet this, E toElement) { * @throws IllegalArgumentException {@inheritDoc} */ @SideEffectFree - public SortedSet tailSet(@GuardSatisfied TreeSet this, E fromElement) { + public @PolyGrowShrink SortedSet tailSet(@GuardSatisfied @PolyGrowShrink TreeSet this, E fromElement) { return tailSet(fromElement, true); } diff --git a/src/java.base/share/classes/java/util/Vector.java b/src/java.base/share/classes/java/util/Vector.java index fbe6d001a4d..7c7ddcd48ad 100644 --- a/src/java.base/share/classes/java/util/Vector.java +++ b/src/java.base/share/classes/java/util/Vector.java @@ -27,6 +27,8 @@ import org.checkerframework.checker.index.qual.GTENegativeOne; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -294,7 +296,7 @@ private Object[] grow() { * @param newSize the new size of this vector * @throws ArrayIndexOutOfBoundsException if the new size is negative */ - public synchronized void setSize(@GuardSatisfied Vector this, @NonNegative int newSize) { + public synchronized void setSize(@GuardSatisfied @Shrinkable Vector this, @NonNegative int newSize) { modCount++; if (newSize > elementData.length) grow(newSize); @@ -349,7 +351,7 @@ public synchronized boolean isEmpty(@GuardSatisfied Vector this) { * @return an enumeration of the components of this vector * @see Iterator */ - public Enumeration elements() { + public @PolyGrowShrink @PolyNonEmpty Enumeration elements(@PolyGrowShrink @PolyNonEmpty Vector this) { return new Enumeration() { int count = 0; @@ -573,7 +575,7 @@ public synchronized void setElementAt(@GuardSatisfied Vector this, E obj, @No * @throws ArrayIndexOutOfBoundsException if the index is out of range * ({@code index < 0 || index >= size()}) */ - public synchronized void removeElementAt(@GuardSatisfied Vector this, @NonNegative int index) { + public synchronized void removeElementAt(@GuardSatisfied @Shrinkable Vector this, @NonNegative int index) { if (index >= elementCount) { throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount); @@ -661,7 +663,7 @@ public synchronized void addElement(@GuardSatisfied Vector this, E obj) { * @return {@code true} if the argument was a component of this * vector; {@code false} otherwise. */ - public synchronized boolean removeElement(@GuardSatisfied Vector this, Object obj) { + public synchronized boolean removeElement(@GuardSatisfied @Shrinkable Vector this, Object obj) { modCount++; int i = indexOf(obj); if (i >= 0) { @@ -677,7 +679,7 @@ public synchronized boolean removeElement(@GuardSatisfied Vector this, Object *

      This method is identical in functionality to the {@link #clear} * method (which is part of the {@link List} interface). */ - public synchronized void removeAllElements(@GuardSatisfied Vector this) { + public synchronized void removeAllElements(@GuardSatisfied @Shrinkable Vector this) { final Object[] es = elementData; for (int to = elementCount, i = elementCount = 0; i < to; i++) es[i] = null; @@ -843,7 +845,7 @@ public synchronized boolean add(@GuardSatisfied Vector this, E e) { * @return true if the Vector contained the specified element * @since 1.2 */ - public boolean remove(@GuardSatisfied Vector this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@GuardSatisfied @Shrinkable Vector this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { return removeElement(o); } @@ -873,7 +875,7 @@ public void add(@GuardSatisfied Vector this, @NonNegative int index, E elemen * ({@code index < 0 || index >= size()}) * @since 1.2 */ - public synchronized E remove(@GuardSatisfied Vector this, @NonNegative int index) { + public synchronized E remove(@GuardSatisfied @Shrinkable Vector this, @NonNegative int index) { modCount++; if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); @@ -894,7 +896,7 @@ public synchronized E remove(@GuardSatisfied Vector this, @NonNegative int in * * @since 1.2 */ - public void clear(@GuardSatisfied Vector this) { + public void clear(@GuardSatisfied @Shrinkable Vector this) { removeAllElements(); } @@ -962,7 +964,7 @@ public boolean addAll(@GuardSatisfied Vector this, Collection c) * or if the specified collection is null * @since 1.2 */ - public boolean removeAll(@GuardSatisfied Vector this, Collection c) { + public boolean removeAll(@GuardSatisfied @Shrinkable Vector this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -986,7 +988,7 @@ public boolean removeAll(@GuardSatisfied Vector this, Collection this, Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable Vector this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } @@ -996,7 +998,7 @@ public boolean retainAll(@GuardSatisfied Vector this, Collection filter) { + public boolean removeIf(@Shrinkable Vector this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -1158,7 +1160,7 @@ public synchronized String toString(@GuardSatisfied Vector this) { * {@code (fromIndex > toIndex)} */ @SideEffectFree - public synchronized List subList(@GuardSatisfied Vector this, int fromIndex, int toIndex) { + public synchronized @PolyGrowShrink List subList(@GuardSatisfied @PolyGrowShrink Vector this, int fromIndex, int toIndex) { return Collections.synchronizedList(super.subList(fromIndex, toIndex), this); } @@ -1170,7 +1172,7 @@ public synchronized List subList(@GuardSatisfied Vector this, int fromInde * This call shortens the list by {@code (toIndex - fromIndex)} elements. * (If {@code toIndex==fromIndex}, this operation has no effect.) */ - protected synchronized void removeRange(int fromIndex, int toIndex) { + protected synchronized void removeRange(@GuardSatisfied @Shrinkable Vector this, int fromIndex, int toIndex) { modCount++; shiftTailOverGap(elementData, fromIndex, toIndex); } @@ -1241,7 +1243,7 @@ private void writeObject(java.io.ObjectOutputStream s) * * @throws IndexOutOfBoundsException {@inheritDoc} */ - public synchronized ListIterator listIterator(@NonNegative int index) { + public synchronized @PolyGrowShrink ListIterator listIterator(@PolyGrowShrink Vector this, @NonNegative int index) { if (index < 0 || index > elementCount) throw new IndexOutOfBoundsException("Index: "+index); return new ListItr(index); @@ -1255,7 +1257,7 @@ public synchronized ListIterator listIterator(@NonNegative int index) { * * @see #listIterator(int) */ - public synchronized ListIterator listIterator() { + public synchronized @PolyGrowShrink @PolyNonEmpty ListIterator listIterator(@PolyGrowShrink Vector this) { return new ListItr(0); } @@ -1267,7 +1269,7 @@ public synchronized ListIterator listIterator() { * @return an iterator over the elements in this list in proper sequence */ @SideEffectFree - public synchronized Iterator iterator() { + public synchronized @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty Vector this) { return new Itr(); } diff --git a/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java index c4d99dd012d..7b3987b369f 100644 --- a/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java @@ -35,10 +35,13 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -417,7 +420,7 @@ public boolean offer(E e, long timeout, TimeUnit unit) } } - public E poll() { + public E poll(@GuardSatisfied @Shrinkable ArrayBlockingQueue this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -427,7 +430,7 @@ public E poll() { } } - public E take() throws InterruptedException { + public E take(@GuardSatisfied @Shrinkable ArrayBlockingQueue this) throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { @@ -439,7 +442,7 @@ public E take() throws InterruptedException { } } - public E poll(long timeout, TimeUnit unit) throws InterruptedException { + public E poll(@GuardSatisfied @Shrinkable ArrayBlockingQueue this, long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); @@ -524,7 +527,7 @@ public int remainingCapacity() { * @param o element to be removed from this queue, if present * @return {@code true} if this queue changed as a result of the call */ - public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@Shrinkable ArrayBlockingQueue this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o == null) return false; final ReentrantLock lock = this.lock; lock.lock(); @@ -675,7 +678,7 @@ public String toString() { * Atomically removes all of the elements from this queue. * The queue will be empty after this call returns. */ - public void clear() { + public void clear(@GuardSatisfied @Shrinkable ArrayBlockingQueue this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -714,7 +717,7 @@ private static void circularClear(Object[] items, int i, int end) { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c) { + public int drainTo(@GuardSatisfied @Shrinkable ArrayBlockingQueue this, Collection c) { return drainTo(c, Integer.MAX_VALUE); } @@ -724,7 +727,7 @@ public int drainTo(Collection c) { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c, int maxElements) { + public int drainTo(@GuardSatisfied @Shrinkable ArrayBlockingQueue this, Collection c, int maxElements) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); @@ -776,7 +779,7 @@ else if (i > take) * * @return an iterator over the elements in this queue in proper sequence */ - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty ArrayBlockingQueue this) { return new Itr(); } @@ -1490,7 +1493,7 @@ public void forEach(Consumer action) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable ArrayBlockingQueue this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -1498,7 +1501,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable ArrayBlockingQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1506,7 +1509,7 @@ public boolean removeAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable ArrayBlockingQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } diff --git a/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java b/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java index 2180e76e280..e40f9c72e2f 100644 --- a/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java @@ -35,9 +35,13 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; +import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.signedness.qual.UnknownSignedness; @@ -355,7 +359,7 @@ boolean offerLast(E e, long timeout, TimeUnit unit) * @return the head of this deque * @throws InterruptedException if interrupted while waiting */ - E takeFirst() throws InterruptedException; + E takeFirst(@Shrinkable BlockingDeque this) throws InterruptedException; /** * Retrieves and removes the last element of this deque, waiting @@ -364,7 +368,7 @@ boolean offerLast(E e, long timeout, TimeUnit unit) * @return the tail of this deque * @throws InterruptedException if interrupted while waiting */ - E takeLast() throws InterruptedException; + E takeLast(@Shrinkable BlockingDeque this) throws InterruptedException; /** * Retrieves and removes the first element of this deque, waiting @@ -379,7 +383,7 @@ boolean offerLast(E e, long timeout, TimeUnit unit) * waiting time elapses before an element is available * @throws InterruptedException if interrupted while waiting */ - @Nullable E pollFirst(long timeout, TimeUnit unit) + @Nullable E pollFirst(@Shrinkable BlockingDeque this, long timeout, TimeUnit unit) throws InterruptedException; /** @@ -395,7 +399,7 @@ boolean offerLast(E e, long timeout, TimeUnit unit) * waiting time elapses before an element is available * @throws InterruptedException if interrupted while waiting */ - @Nullable E pollLast(long timeout, TimeUnit unit) + @Nullable E pollLast(@Shrinkable BlockingDeque this, long timeout, TimeUnit unit) throws InterruptedException; /** @@ -414,7 +418,7 @@ boolean offerLast(E e, long timeout, TimeUnit unit) * @throws NullPointerException if the specified element is null * (optional) */ - boolean removeFirstOccurrence(Object o); + boolean removeFirstOccurrence(@Shrinkable BlockingDeque this, Object o); /** * Removes the last occurrence of the specified element from this deque. @@ -432,7 +436,7 @@ boolean offerLast(E e, long timeout, TimeUnit unit) * @throws NullPointerException if the specified element is null * (optional) */ - boolean removeLastOccurrence(Object o); + boolean removeLastOccurrence(@Shrinkable BlockingDeque this, Object o); // *** BlockingQueue methods *** @@ -527,7 +531,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * @return the head of the queue represented by this deque * @throws NoSuchElementException if this deque is empty */ - E remove(@NonEmpty BlockingDeque this); + E remove(@GuardSatisfied @NonEmpty @Shrinkable BlockingDeque this); /** * Retrieves and removes the head of the queue represented by this deque @@ -538,7 +542,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * * @return the head of this deque, or {@code null} if this deque is empty */ - @Nullable E poll(); + @Nullable E poll(@Shrinkable BlockingDeque this); /** * Retrieves and removes the head of the queue represented by this deque @@ -550,7 +554,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * @return the head of this deque * @throws InterruptedException if interrupted while waiting */ - E take() throws InterruptedException; + E take(@Shrinkable BlockingDeque this) throws InterruptedException; /** * Retrieves and removes the head of the queue represented by this deque @@ -564,7 +568,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * specified waiting time elapses before an element is available * @throws InterruptedException if interrupted while waiting */ - @Nullable E poll(long timeout, TimeUnit unit) + @Nullable E poll(@Shrinkable BlockingDeque this, long timeout, TimeUnit unit) throws InterruptedException; /** @@ -610,7 +614,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * @throws NullPointerException if the specified element is null * (optional) */ - boolean remove(@UnknownSignedness Object o); + boolean remove(@Shrinkable BlockingDeque this, @UnknownSignedness Object o); /** * Returns {@code true} if this deque contains the specified element. @@ -644,7 +648,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * @return an iterator over the elements in this deque in proper sequence */ @SideEffectFree - Iterator iterator(); + @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty BlockingDeque this); // *** Stack methods *** diff --git a/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java index b4e99d9d203..7ad116a16c3 100644 --- a/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java @@ -35,6 +35,8 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.Shrinkable; +import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; @@ -317,7 +319,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * @throws NullPointerException if the specified element is null * (optional) */ - boolean remove(@UnknownSignedness Object o); + boolean remove(@Shrinkable BlockingQueue this, @UnknownSignedness Object o); /** * Returns {@code true} if this queue contains the specified element. @@ -359,7 +361,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * queue, or some property of an element of this queue prevents * it from being added to the specified collection */ - int drainTo(Collection c); + int drainTo(@GuardSatisfied @Shrinkable BlockingQueue this, Collection c); /** * Removes at most the given number of available elements from @@ -384,5 +386,5 @@ boolean offer(E e, long timeout, TimeUnit unit) * queue, or some property of an element of this queue prevents * it from being added to the specified collection */ - int drainTo(Collection c, int maxElements); + int drainTo(@GuardSatisfied @Shrinkable BlockingQueue this, Collection c, int maxElements); } diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java index 2d8e66e2300..0333416ff65 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java @@ -35,10 +35,13 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -928,7 +931,7 @@ public E getLast(@NonEmpty ConcurrentLinkedDeque this) { return screenNullResult(peekLast()); } - public @Nullable E pollFirst() { + public @Nullable E pollFirst(@GuardSatisfied @Shrinkable ConcurrentLinkedDeque this) { restart: for (;;) { for (Node first = first(), p = first;;) { final E item; @@ -949,7 +952,7 @@ public E getLast(@NonEmpty ConcurrentLinkedDeque this) { } } - public @Nullable E pollLast() { + public @Nullable E pollLast(@GuardSatisfied @Shrinkable ConcurrentLinkedDeque this) { restart: for (;;) { for (Node last = last(), p = last;;) { final E item; @@ -973,14 +976,14 @@ public E getLast(@NonEmpty ConcurrentLinkedDeque this) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeFirst(@NonEmpty ConcurrentLinkedDeque this) { + public E removeFirst(@GuardSatisfied @NonEmpty @Shrinkable ConcurrentLinkedDeque this) { return screenNullResult(pollFirst()); } /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeLast(@NonEmpty ConcurrentLinkedDeque this) { + public E removeLast(@GuardSatisfied @NonEmpty @Shrinkable ConcurrentLinkedDeque this) { return screenNullResult(pollLast()); } @@ -1010,19 +1013,19 @@ public boolean add(E e) { return offerLast(e); } - public @Nullable E poll() { return pollFirst(); } + public @Nullable E poll(@Shrinkable ConcurrentLinkedDeque this) { return pollFirst(); } @Pure public @Nullable E peek() { return peekFirst(); } /** * @throws NoSuchElementException {@inheritDoc} */ - public E remove(@NonEmpty ConcurrentLinkedDeque this) { return removeFirst(); } + public E remove(@NonEmpty @Shrinkable ConcurrentLinkedDeque this) { return removeFirst(); } /** * @throws NoSuchElementException {@inheritDoc} */ - public E pop(@NonEmpty ConcurrentLinkedDeque this) { return removeFirst(); } + public E pop(@GuardSatisfied @NonEmpty @Shrinkable ConcurrentLinkedDeque this) { return removeFirst(); } /** * @throws NoSuchElementException {@inheritDoc} @@ -1046,7 +1049,7 @@ public boolean add(E e) { * @return {@code true} if the deque contained the specified element * @throws NullPointerException if the specified element is null */ - public boolean removeFirstOccurrence(Object o) { + public boolean removeFirstOccurrence(@Shrinkable ConcurrentLinkedDeque this, Object o) { Objects.requireNonNull(o); for (Node p = first(); p != null; p = succ(p)) { final E item; @@ -1072,7 +1075,7 @@ public boolean removeFirstOccurrence(Object o) { * @return {@code true} if the deque contained the specified element * @throws NullPointerException if the specified element is null */ - public boolean removeLastOccurrence(Object o) { + public boolean removeLastOccurrence(@Shrinkable ConcurrentLinkedDeque this, Object o) { Objects.requireNonNull(o); for (Node p = last(); p != null; p = pred(p)) { final E item; @@ -1164,7 +1167,7 @@ public int size() { * @return {@code true} if the deque contained the specified element * @throws NullPointerException if the specified element is null */ - public boolean remove(@GuardSatisfied @UnknownSignedness Object o) { + public boolean remove(@Shrinkable ConcurrentLinkedDeque this, @GuardSatisfied @UnknownSignedness Object o) { return removeFirstOccurrence(o); } @@ -1234,7 +1237,7 @@ else if (p.prev == p) // NEXT_TERMINATOR /** * Removes all of the elements from this deque. */ - public void clear() { + public void clear(@GuardSatisfied @Shrinkable ConcurrentLinkedDeque this) { while (pollFirst() != null) ; } @@ -1367,7 +1370,7 @@ else if (a != null && size <= a.length) { * @return an iterator over the elements in this deque in proper sequence */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty ConcurrentLinkedDeque this) { return new Itr(); } @@ -1381,7 +1384,7 @@ public Iterator iterator() { * * @return an iterator over the elements in this deque in reverse order */ - public Iterator descendingIterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator descendingIterator(@PolyGrowShrink @PolyNonEmpty ConcurrentLinkedDeque this) { return new DescendingItr(); } @@ -1635,7 +1638,7 @@ private void readObject(java.io.ObjectInputStream s) /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable ConcurrentLinkedDeque this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -1643,7 +1646,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable ConcurrentLinkedDeque this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1651,7 +1654,7 @@ public boolean removeAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable ConcurrentLinkedDeque this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java index a8c029fdd3f..92876af30e2 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java @@ -35,10 +35,13 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -396,7 +399,7 @@ else if (p == q) } } - public @Nullable E poll() { + public @Nullable E poll(@GuardSatisfied @Shrinkable ConcurrentLinkedQueue this) { restartFromHead: for (;;) { for (Node h = head, p = h, q;; p = q) { final E item; @@ -540,7 +543,7 @@ public boolean contains(@GuardSatisfied @UnknownSignedness Object o) { * @param o element to be removed from this queue, if present * @return {@code true} if this queue changed as a result of the call */ - public boolean remove(@GuardSatisfied @UnknownSignedness Object o) { + public boolean remove(@Shrinkable ConcurrentLinkedQueue this, @GuardSatisfied @UnknownSignedness Object o) { if (o == null) return false; restartFromHead: for (;;) { for (Node p = head, pred = null; p != null; ) { @@ -750,7 +753,7 @@ else if (a != null && size <= a.length) { * @return an iterator over the elements in this queue in proper sequence */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty ConcurrentLinkedQueue this) { return new Itr(); } @@ -988,7 +991,7 @@ public Spliterator spliterator() { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable ConcurrentLinkedQueue this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -996,7 +999,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable ConcurrentLinkedQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1004,12 +1007,12 @@ public boolean removeAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable ConcurrentLinkedQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } - public void clear() { + public void clear(@GuardSatisfied @Shrinkable ConcurrentLinkedQueue this) { bulkRemove(e -> true); } diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java index 11038b52fe6..6d3c1ce27aa 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java @@ -35,10 +35,12 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -294,7 +296,7 @@ public void clear() { * @return an iterator over the elements in this set in ascending order */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this) { return m.navigableKeySet().iterator(); } @@ -303,7 +305,7 @@ public Iterator iterator() { * * @return an iterator over the elements in this set in descending order */ - public Iterator descendingIterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator descendingIterator(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this) { return m.descendingKeySet().iterator(); } @@ -433,7 +435,7 @@ public E last(@NonEmpty ConcurrentSkipListSet this) { * {@code toElement} is null * @throws IllegalArgumentException {@inheritDoc} */ - public NavigableSet subSet(E fromElement, + public @PolyGrowShrink @PolyNonEmpty NavigableSet subSet(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this, E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { @@ -447,7 +449,7 @@ public NavigableSet subSet(E fromElement, * @throws NullPointerException if {@code toElement} is null * @throws IllegalArgumentException {@inheritDoc} */ - public NavigableSet headSet(E toElement, boolean inclusive) { + public @PolyGrowShrink @PolyNonEmpty NavigableSet headSet(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this, E toElement, boolean inclusive) { return new ConcurrentSkipListSet(m.headMap(toElement, inclusive)); } @@ -456,7 +458,7 @@ public NavigableSet headSet(E toElement, boolean inclusive) { * @throws NullPointerException if {@code fromElement} is null * @throws IllegalArgumentException {@inheritDoc} */ - public NavigableSet tailSet(E fromElement, boolean inclusive) { + public @PolyGrowShrink @PolyNonEmpty NavigableSet tailSet(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this, E fromElement, boolean inclusive) { return new ConcurrentSkipListSet(m.tailMap(fromElement, inclusive)); } @@ -466,7 +468,7 @@ public NavigableSet tailSet(E fromElement, boolean inclusive) { * {@code toElement} is null * @throws IllegalArgumentException {@inheritDoc} */ - public NavigableSet subSet(E fromElement, E toElement) { + public @PolyGrowShrink @PolyNonEmpty NavigableSet subSet(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this, E fromElement, E toElement) { return subSet(fromElement, true, toElement, false); } @@ -475,7 +477,7 @@ public NavigableSet subSet(E fromElement, E toElement) { * @throws NullPointerException if {@code toElement} is null * @throws IllegalArgumentException {@inheritDoc} */ - public NavigableSet headSet(E toElement) { + public @PolyGrowShrink @PolyNonEmpty NavigableSet headSet(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this, E toElement) { return headSet(toElement, false); } @@ -484,7 +486,7 @@ public NavigableSet headSet(E toElement) { * @throws NullPointerException if {@code fromElement} is null * @throws IllegalArgumentException {@inheritDoc} */ - public NavigableSet tailSet(E fromElement) { + public @PolyGrowShrink @PolyNonEmpty NavigableSet tailSet(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this, E fromElement) { return tailSet(fromElement, true); } @@ -500,7 +502,7 @@ public NavigableSet tailSet(E fromElement) { * * @return a reverse order view of this set */ - public NavigableSet descendingSet() { + public @PolyGrowShrink @PolyNonEmpty NavigableSet descendingSet(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this) { return new ConcurrentSkipListSet(m.descendingMap()); } diff --git a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java index 650887a1266..daea4365105 100644 --- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java +++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java @@ -34,10 +34,13 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -491,7 +494,7 @@ public void add(int index, E element) { * * @throws IndexOutOfBoundsException {@inheritDoc} */ - public E remove(int index) { + public E remove(@GuardSatisfied @Shrinkable CopyOnWriteArrayList this, int index) { synchronized (lock) { Object[] es = getArray(); int len = es.length; @@ -523,7 +526,7 @@ public E remove(int index) { * @param o element to be removed from this list, if present * @return {@code true} if this list contained the specified element */ - public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@Shrinkable CopyOnWriteArrayList this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { Object[] snapshot = getArray(); int index = indexOfRange(o, snapshot, 0, snapshot.length); return index >= 0 && remove(o, snapshot, index); @@ -533,7 +536,7 @@ public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { * A version of remove(Object) using the strong hint that given * recent snapshot contains o at the given index. */ - private boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o, Object[] snapshot, int index) { + private boolean remove(@Shrinkable CopyOnWriteArrayList this, @GuardSatisfied @Nullable @UnknownSignedness Object o, Object[] snapshot, int index) { synchronized (lock) { Object[] current = getArray(); int len = current.length; @@ -576,7 +579,7 @@ private boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o, Ob * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range * ({@code fromIndex < 0 || toIndex > size() || toIndex < fromIndex}) */ - void removeRange(int fromIndex, int toIndex) { + void removeRange(@GuardSatisfied @Shrinkable CopyOnWriteArrayList this, int fromIndex, int toIndex) { synchronized (lock) { Object[] es = getArray(); int len = es.length; @@ -671,7 +674,7 @@ public boolean containsAll(Collection c) { * or if the specified collection is null * @see #remove(Object) */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable CopyOnWriteArrayList this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -692,7 +695,7 @@ public boolean removeAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable CopyOnWriteArrayList this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } @@ -739,7 +742,7 @@ public int addAllAbsent(Collection c) { * Removes all of the elements from this list. * The list will be empty after this call returns. */ - public void clear() { + public void clear(@GuardSatisfied @Shrinkable CopyOnWriteArrayList this) { synchronized (lock) { setArray(new Object[0]); } @@ -832,7 +835,7 @@ public void forEach(Consumer action) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable CopyOnWriteArrayList this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -1043,7 +1046,7 @@ public int hashCode() { * * @return an iterator over the elements in this list in proper sequence */ - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty CopyOnWriteArrayList this) { return new COWIterator(getArray(), 0); } @@ -1055,7 +1058,7 @@ public Iterator iterator() { * traversing the iterator. The iterator does NOT support the * {@code remove}, {@code set} or {@code add} methods. */ - public ListIterator listIterator() { + public @PolyGrowShrink @PolyNonEmpty ListIterator listIterator(@PolyGrowShrink @PolyNonEmpty CopyOnWriteArrayList this) { return new COWIterator(getArray(), 0); } @@ -1069,7 +1072,7 @@ public ListIterator listIterator() { * * @throws IndexOutOfBoundsException {@inheritDoc} */ - public ListIterator listIterator(int index) { + public @PolyGrowShrink ListIterator listIterator(@PolyGrowShrink CopyOnWriteArrayList this, int index) { Object[] es = getArray(); int len = es.length; if (index < 0 || index > len) @@ -1198,7 +1201,7 @@ public void forEachRemaining(Consumer action) { * @return a view of the specified range within this list * @throws IndexOutOfBoundsException {@inheritDoc} */ - public List subList(int fromIndex, int toIndex) { + public @PolyGrowShrink List subList(@PolyGrowShrink CopyOnWriteArrayList this, int fromIndex, int toIndex) { synchronized (lock) { Object[] es = getArray(); int len = es.length; diff --git a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java index 017289436ca..b0078296d26 100644 --- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java +++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java @@ -35,10 +35,12 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -405,7 +407,7 @@ public boolean retainAll(Collection iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty CopyOnWriteArraySet this) { return al.iterator(); } diff --git a/src/java.base/share/classes/java/util/concurrent/DelayQueue.java b/src/java.base/share/classes/java/util/concurrent/DelayQueue.java index d619b0e085f..e9ed49e5403 100644 --- a/src/java.base/share/classes/java/util/concurrent/DelayQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/DelayQueue.java @@ -49,6 +49,10 @@ import org.checkerframework.framework.qual.AnnotatedFor; import static java.util.concurrent.TimeUnit.NANOSECONDS; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.index.qual.Shrinkable; import java.util.AbstractQueue; import java.util.Collection; import java.util.Iterator; @@ -201,7 +205,7 @@ public boolean offer(E e, long timeout, TimeUnit unit) { * @return the head of this queue, or {@code null} if this * queue has no elements with an expired delay */ - public @Nullable E poll() { + public @Nullable E poll(@GuardSatisfied @Shrinkable DelayQueue this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -221,7 +225,7 @@ public boolean offer(E e, long timeout, TimeUnit unit) { * @return the head of this queue * @throws InterruptedException {@inheritDoc} */ - public E take() throws InterruptedException { + public E take(@GuardSatisfied @Shrinkable DelayQueue this) throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { @@ -265,7 +269,7 @@ public E take() throws InterruptedException { * an expired delay becomes available * @throws InterruptedException {@inheritDoc} */ - public @Nullable E poll(long timeout, TimeUnit unit) throws InterruptedException { + public @Nullable E poll(@GuardSatisfied @Shrinkable DelayQueue this, long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); @@ -344,7 +348,7 @@ public int size() { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c) { + public int drainTo(@GuardSatisfied @Shrinkable DelayQueue this, Collection c) { return drainTo(c, Integer.MAX_VALUE); } @@ -354,7 +358,7 @@ public int drainTo(Collection c) { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c, int maxElements) { + public int drainTo(@GuardSatisfied @Shrinkable DelayQueue this, Collection c, int maxElements) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); @@ -384,7 +388,7 @@ public int drainTo(Collection c, int maxElements) { * Elements with an unexpired delay are not waited for; they are * simply discarded from the queue. */ - public void clear() { + public void clear(@GuardSatisfied @Shrinkable DelayQueue this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -478,7 +482,7 @@ public int remainingCapacity() { * Removes a single instance of the specified element from this * queue, if it is present, whether or not it has expired. */ - public boolean remove(@UnknownSignedness Object o) { + public boolean remove(@Shrinkable DelayQueue this, @UnknownSignedness Object o) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -517,7 +521,7 @@ void removeEQ(Object o) { * @return an iterator over the elements in this queue */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty DelayQueue this) { return new Itr(toArray()); } diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java index d25e44d2d16..2c5ecfbb033 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java @@ -35,10 +35,13 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -258,7 +261,7 @@ private boolean linkLast(Node node) { /** * Removes and returns first element, or null if empty. */ - private E unlinkFirst() { + private E unlinkFirst(@Shrinkable LinkedBlockingDeque this) { // assert lock.isHeldByCurrentThread(); Node f = first; if (f == null) @@ -280,7 +283,7 @@ private E unlinkFirst() { /** * Removes and returns last element, or null if empty. */ - private E unlinkLast() { + private E unlinkLast(@Shrinkable LinkedBlockingDeque this) { // assert lock.isHeldByCurrentThread(); Node l = last; if (l == null) @@ -302,7 +305,7 @@ private E unlinkLast() { /** * Unlinks x. */ - void unlink(Node x) { + void unlink(@Shrinkable LinkedBlockingDeque this, Node x) { // assert lock.isHeldByCurrentThread(); // assert x.item != null; Node p = x.prev; @@ -455,7 +458,7 @@ public boolean offerLast(E e, long timeout, TimeUnit unit) /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeFirst(@NonEmpty LinkedBlockingDeque this) { + public E removeFirst(@GuardSatisfied @NonEmpty @Shrinkable LinkedBlockingDeque this) { E x = pollFirst(); if (x == null) throw new NoSuchElementException(); return x; @@ -464,13 +467,13 @@ public E removeFirst(@NonEmpty LinkedBlockingDeque this) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeLast(@NonEmpty LinkedBlockingDeque this) { + public E removeLast(@GuardSatisfied @NonEmpty @Shrinkable LinkedBlockingDeque this) { E x = pollLast(); if (x == null) throw new NoSuchElementException(); return x; } - public @Nullable E pollFirst() { + public @Nullable E pollFirst(@GuardSatisfied @Shrinkable LinkedBlockingDeque this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -480,7 +483,7 @@ public E removeLast(@NonEmpty LinkedBlockingDeque this) { } } - public @Nullable E pollLast() { + public @Nullable E pollLast(@GuardSatisfied @Shrinkable LinkedBlockingDeque this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -490,7 +493,7 @@ public E removeLast(@NonEmpty LinkedBlockingDeque this) { } } - public E takeFirst() throws InterruptedException { + public E takeFirst(@GuardSatisfied @Shrinkable LinkedBlockingDeque this) throws InterruptedException { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -503,7 +506,7 @@ public E takeFirst() throws InterruptedException { } } - public E takeLast() throws InterruptedException { + public E takeLast(@GuardSatisfied @Shrinkable LinkedBlockingDeque this) throws InterruptedException { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -516,7 +519,7 @@ public E takeLast() throws InterruptedException { } } - public @Nullable E pollFirst(long timeout, TimeUnit unit) + public @Nullable E pollFirst(@GuardSatisfied @Shrinkable LinkedBlockingDeque this, long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; @@ -534,7 +537,7 @@ public E takeLast() throws InterruptedException { } } - public @Nullable E pollLast(long timeout, TimeUnit unit) + public @Nullable E pollLast(@GuardSatisfied @Shrinkable LinkedBlockingDeque this, long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; @@ -592,7 +595,7 @@ public E getLast(@NonEmpty LinkedBlockingDeque this) { } } - public boolean removeFirstOccurrence(Object o) { + public boolean removeFirstOccurrence(@Shrinkable LinkedBlockingDeque this, Object o) { if (o == null) return false; final ReentrantLock lock = this.lock; lock.lock(); @@ -609,7 +612,7 @@ public boolean removeFirstOccurrence(Object o) { } } - public boolean removeLastOccurrence(Object o) { + public boolean removeLastOccurrence(@Shrinkable LinkedBlockingDeque this, Object o) { if (o == null) return false; final ReentrantLock lock = this.lock; lock.lock(); @@ -678,19 +681,19 @@ public boolean offer(E e, long timeout, TimeUnit unit) * @return the head of the queue represented by this deque * @throws NoSuchElementException if this deque is empty */ - public E remove(@NonEmpty LinkedBlockingDeque this) { + public E remove(@GuardSatisfied @NonEmpty @Shrinkable LinkedBlockingDeque this) { return removeFirst(); } - public @Nullable E poll() { + public @Nullable E poll(@GuardSatisfied @Shrinkable LinkedBlockingDeque this) { return pollFirst(); } - public E take() throws InterruptedException { + public E take(@GuardSatisfied @Shrinkable LinkedBlockingDeque this) throws InterruptedException { return takeFirst(); } - public @Nullable E poll(long timeout, TimeUnit unit) throws InterruptedException { + public @Nullable E poll(@GuardSatisfied @Shrinkable LinkedBlockingDeque this, long timeout, TimeUnit unit) throws InterruptedException { return pollFirst(timeout, unit); } @@ -740,7 +743,7 @@ public int remainingCapacity() { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c) { + public int drainTo(@GuardSatisfied @Shrinkable LinkedBlockingDeque this, Collection c) { return drainTo(c, Integer.MAX_VALUE); } @@ -750,7 +753,7 @@ public int drainTo(Collection c) { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c, int maxElements) { + public int drainTo(@GuardSatisfied @Shrinkable LinkedBlockingDeque this, Collection c, int maxElements) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); @@ -783,7 +786,7 @@ public void push(E e) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E pop(@NonEmpty LinkedBlockingDeque this) { + public E pop(@GuardSatisfied @NonEmpty @Shrinkable LinkedBlockingDeque this) { return removeFirst(); } @@ -803,7 +806,7 @@ public E pop(@NonEmpty LinkedBlockingDeque this) { * @param o element to be removed from this deque, if present * @return {@code true} if this deque changed as a result of the call */ - public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@Shrinkable LinkedBlockingDeque this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { return removeFirstOccurrence(o); } @@ -998,7 +1001,7 @@ public String toString() { * Atomically removes all of the elements from this deque. * The deque will be empty after this call returns. */ - public void clear() { + public void clear(@GuardSatisfied @Shrinkable LinkedBlockingDeque this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -1038,7 +1041,7 @@ Node succ(Node p) { * * @return an iterator over the elements in this deque in proper sequence */ - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty LinkedBlockingDeque this) { return new Itr(); } @@ -1052,7 +1055,7 @@ public Iterator iterator() { * * @return an iterator over the elements in this deque in reverse order */ - public Iterator descendingIterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator descendingIterator(@PolyGrowShrink @PolyNonEmpty LinkedBlockingDeque this) { return new DescendingItr(); } @@ -1354,7 +1357,7 @@ void forEachFrom(Consumer action, Node p) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable LinkedBlockingDeque this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -1362,7 +1365,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable LinkedBlockingDeque this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1370,7 +1373,7 @@ public boolean removeAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable LinkedBlockingDeque this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java index 4336f5a701c..dc52c8b1cf8 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java @@ -35,9 +35,12 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -438,7 +441,7 @@ public boolean offer(E e) { return true; } - public E take() throws InterruptedException { + public E take(@GuardSatisfied @Shrinkable LinkedBlockingQueue this) throws InterruptedException { final E x; final int c; final AtomicInteger count = this.count; @@ -460,7 +463,7 @@ public E take() throws InterruptedException { return x; } - public @Nullable E poll(long timeout, TimeUnit unit) throws InterruptedException { + public @Nullable E poll(@GuardSatisfied @Shrinkable LinkedBlockingQueue this, long timeout, TimeUnit unit) throws InterruptedException { final E x; final int c; long nanos = unit.toNanos(timeout); @@ -485,7 +488,7 @@ public E take() throws InterruptedException { return x; } - public @Nullable E poll() { + public @Nullable E poll(@GuardSatisfied @Shrinkable LinkedBlockingQueue this) { final AtomicInteger count = this.count; if (count.get() == 0) return null; @@ -549,7 +552,7 @@ void unlink(Node p, Node pred) { * @param o element to be removed from this queue, if present * @return {@code true} if this queue changed as a result of the call */ - public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@Shrinkable LinkedBlockingQueue this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o == null) return false; fullyLock(); try { @@ -680,7 +683,7 @@ public String toString() { * Atomically removes all of the elements from this queue. * The queue will be empty after this call returns. */ - public void clear() { + public void clear(@GuardSatisfied @Shrinkable LinkedBlockingQueue this) { fullyLock(); try { for (Node p, h = head; (p = h.next) != null; h = p) { @@ -702,7 +705,7 @@ public void clear() { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c) { + public int drainTo(@GuardSatisfied @Shrinkable LinkedBlockingQueue this, Collection c) { return drainTo(c, Integer.MAX_VALUE); } @@ -712,7 +715,7 @@ public int drainTo(Collection c) { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c, int maxElements) { + public int drainTo(@GuardSatisfied @Shrinkable LinkedBlockingQueue this, Collection c, int maxElements) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); @@ -772,7 +775,7 @@ Node succ(Node p) { * * @return an iterator over the elements in this queue in proper sequence */ - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty LinkedBlockingQueue this) { return new Itr(); } @@ -1037,7 +1040,7 @@ void forEachFrom(Consumer action, Node p) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable LinkedBlockingQueue this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -1045,7 +1048,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable LinkedBlockingQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1053,7 +1056,7 @@ public boolean removeAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable LinkedBlockingQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java b/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java index f7293556771..7ff25b8deda 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java @@ -35,10 +35,13 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -1253,7 +1256,7 @@ public boolean add(E e) { * * @throws NullPointerException if the specified element is null */ - public boolean tryTransfer(E e) { + public boolean tryTransfer(@GuardSatisfied @Shrinkable LinkedTransferQueue this, E e) { return xfer(e, true, NOW, 0L) == null; } @@ -1268,7 +1271,7 @@ public boolean tryTransfer(E e) { * * @throws NullPointerException if the specified element is null */ - public void transfer(E e) throws InterruptedException { + public void transfer(@GuardSatisfied @Shrinkable LinkedTransferQueue this, E e) throws InterruptedException { if (xfer(e, true, SYNC, 0L) != null) { Thread.interrupted(); // failure possible only due to interrupt throw new InterruptedException(); @@ -1289,7 +1292,7 @@ public void transfer(E e) throws InterruptedException { * * @throws NullPointerException if the specified element is null */ - public boolean tryTransfer(E e, long timeout, TimeUnit unit) + public boolean tryTransfer(@GuardSatisfied @Shrinkable LinkedTransferQueue this, E e, long timeout, TimeUnit unit) throws InterruptedException { if (xfer(e, true, TIMED, unit.toNanos(timeout)) == null) return true; @@ -1298,7 +1301,7 @@ public boolean tryTransfer(E e, long timeout, TimeUnit unit) throw new InterruptedException(); } - public E take() throws InterruptedException { + public E take(@GuardSatisfied @Shrinkable LinkedTransferQueue this) throws InterruptedException { E e = xfer(null, false, SYNC, 0L); if (e != null) return e; @@ -1306,14 +1309,14 @@ public E take() throws InterruptedException { throw new InterruptedException(); } - public E poll(long timeout, TimeUnit unit) throws InterruptedException { + public E poll(@GuardSatisfied @Shrinkable LinkedTransferQueue this, long timeout, TimeUnit unit) throws InterruptedException { E e = xfer(null, false, TIMED, unit.toNanos(timeout)); if (e != null || !Thread.interrupted()) return e; throw new InterruptedException(); } - public E poll() { + public E poll(@GuardSatisfied @Shrinkable LinkedTransferQueue this) { return xfer(null, false, NOW, 0L); } @@ -1321,7 +1324,7 @@ public E poll() { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c) { + public int drainTo(@GuardSatisfied @Shrinkable LinkedTransferQueue this, Collection c) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); @@ -1335,7 +1338,7 @@ public int drainTo(Collection c) { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c, int maxElements) { + public int drainTo(@GuardSatisfied @Shrinkable LinkedTransferQueue this, Collection c, int maxElements) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); @@ -1354,7 +1357,7 @@ public int drainTo(Collection c, int maxElements) { * * @return an iterator over the elements in this queue in proper sequence */ - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty LinkedTransferQueue this) { return new Itr(); } @@ -1438,7 +1441,7 @@ public int getWaitingConsumerCount() { * @param o element to be removed from this queue, if present * @return {@code true} if this queue changed as a result of the call */ - public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@Shrinkable LinkedTransferQueue this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o == null) return false; restartFromHead: for (;;) { for (Node p = head, pred = null; p != null; ) { @@ -1558,7 +1561,7 @@ private void readObject(java.io.ObjectInputStream s) /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable LinkedTransferQueue this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -1566,7 +1569,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable LinkedTransferQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1574,12 +1577,12 @@ public boolean removeAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable LinkedTransferQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } - public void clear() { + public void clear(@GuardSatisfied @Shrinkable LinkedTransferQueue this) { bulkRemove(e -> true); } diff --git a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java index 157be54e2d5..bbc80761c7f 100644 --- a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java @@ -35,10 +35,13 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -531,7 +534,7 @@ public boolean offer(E e, long timeout, TimeUnit unit) { return offer(e); // never need to block } - public @Nullable E poll() { + public @Nullable E poll(@GuardSatisfied @Shrinkable PriorityBlockingQueue this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -541,7 +544,7 @@ public boolean offer(E e, long timeout, TimeUnit unit) { } } - public E take() throws InterruptedException { + public E take(@GuardSatisfied @Shrinkable PriorityBlockingQueue this) throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); E result; @@ -554,7 +557,7 @@ public E take() throws InterruptedException { return result; } - public @Nullable E poll(long timeout, TimeUnit unit) throws InterruptedException { + public @Nullable E poll(@GuardSatisfied @Shrinkable PriorityBlockingQueue this, long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); @@ -659,7 +662,7 @@ private void removeAt(int i) { * @param o element to be removed from this queue, if present * @return {@code true} if this queue changed as a result of the call */ - public boolean remove(@Nullable @UnknownSignedness Object o) { + public boolean remove(@Shrinkable PriorityBlockingQueue this, @Nullable @UnknownSignedness Object o) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -724,7 +727,7 @@ public String toString() { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c) { + public int drainTo(@GuardSatisfied @Shrinkable PriorityBlockingQueue this, Collection c) { return drainTo(c, Integer.MAX_VALUE); } @@ -734,7 +737,7 @@ public int drainTo(Collection c) { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c, int maxElements) { + public int drainTo(@GuardSatisfied @Shrinkable PriorityBlockingQueue this, Collection c, int maxElements) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); @@ -758,7 +761,7 @@ public int drainTo(Collection c, int maxElements) { * Atomically removes all of the elements from this queue. * The queue will be empty after this call returns. */ - public void clear() { + public void clear(@GuardSatisfied @Shrinkable PriorityBlockingQueue this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -856,7 +859,7 @@ public void clear() { * * @return an iterator over the elements in this queue */ - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty PriorityBlockingQueue this) { return new Itr(toArray()); } @@ -1030,7 +1033,7 @@ public Spliterator spliterator() { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable PriorityBlockingQueue this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -1038,7 +1041,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable PriorityBlockingQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1046,7 +1049,7 @@ public boolean removeAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable PriorityBlockingQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } diff --git a/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java b/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java index ff89b1915f7..b35a4869cf3 100644 --- a/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java @@ -36,8 +36,11 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -894,7 +897,7 @@ public boolean offer(E e) { * @return the head of this queue * @throws InterruptedException {@inheritDoc} */ - public E take() throws InterruptedException { + public E take(@GuardSatisfied @Shrinkable SynchronousQueue this) throws InterruptedException { E e = transferer.transfer(null, false, 0); if (e != null) return e; @@ -911,7 +914,7 @@ public E take() throws InterruptedException { * specified waiting time elapses before an element is present * @throws InterruptedException {@inheritDoc} */ - public E poll(long timeout, TimeUnit unit) throws InterruptedException { + public E poll(@GuardSatisfied @Shrinkable SynchronousQueue this, long timeout, TimeUnit unit) throws InterruptedException { E e = transferer.transfer(null, true, unit.toNanos(timeout)); if (e != null || !Thread.interrupted()) return e; @@ -925,7 +928,7 @@ public E poll(long timeout, TimeUnit unit) throws InterruptedException { * @return the head of this queue, or {@code null} if no * element is available */ - public E poll() { + public E poll(@GuardSatisfied @Shrinkable SynchronousQueue this) { return transferer.transfer(null, true, 0); } @@ -966,7 +969,7 @@ public int remainingCapacity() { * Does nothing. * A {@code SynchronousQueue} has no internal capacity. */ - public void clear() { + public void clear(@GuardSatisfied @Shrinkable SynchronousQueue this) { } /** @@ -989,7 +992,7 @@ public boolean contains(@GuardSatisfied @Nullable @UnknownSignedness Object o) { * @param o the element to remove * @return {@code false} */ - public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@Shrinkable SynchronousQueue this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { return false; } @@ -1012,7 +1015,7 @@ public boolean containsAll(Collection c) { * @param c the collection * @return {@code false} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable SynchronousQueue this, Collection c) { return false; } @@ -1023,7 +1026,7 @@ public boolean removeAll(Collection c) { * @param c the collection * @return {@code false} */ - public boolean retainAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable SynchronousQueue this, Collection c) { return false; } @@ -1046,7 +1049,7 @@ public E peek() { * @return an empty iterator */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty SynchronousQueue this) { return Collections.emptyIterator(); } @@ -1100,7 +1103,7 @@ public String toString() { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c) { + public int drainTo(@GuardSatisfied @Shrinkable SynchronousQueue this, Collection c) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); @@ -1116,7 +1119,7 @@ public int drainTo(Collection c) { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c, int maxElements) { + public int drainTo(@GuardSatisfied @Shrinkable SynchronousQueue this, Collection c, int maxElements) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/BottomGrowShrink.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/BottomGrowShrink.java new file mode 100644 index 00000000000..2df971a0a66 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/BottomGrowShrink.java @@ -0,0 +1,20 @@ +package org.checkerframework.checker.index.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * The bottom qualifier in the GrowShrink hierarchy. Programmers should rarely write this type. + * + * @checker_framework.manual #growonly-checker Grow-only Checker + * @checker_framework.manual #bottom-type the bottom type + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({GrowOnly.class, UncheckedShrinkable.class}) +public @interface BottomGrowShrink {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/GrowOnly.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/GrowOnly.java new file mode 100644 index 00000000000..61644656ca7 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/GrowOnly.java @@ -0,0 +1,21 @@ +package org.checkerframework.checker.index.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * An expression of type {@code @GrowOnly} may not be used to remove elements, e.g., by calling + * {@code remove()} or {@code clear()} on it. The underlying collection is guaranteed not to shrink + * via operations on aliases. + * + * @checker_framework.manual #growonly-checker Grow-only Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({UnshrinkableRef.class}) +public @interface GrowOnly {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/PolyGrowShrink.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/PolyGrowShrink.java new file mode 100644 index 00000000000..2f10e01b96e --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/PolyGrowShrink.java @@ -0,0 +1,20 @@ +package org.checkerframework.checker.index.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.PolymorphicQualifier; + +/** + * A polymorphic qualifier for @GrowOnly type system. + * + * @checker_framework.manual #index-checker Index Checker + * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@PolymorphicQualifier(UnshrinkableRef.class) +public @interface PolyGrowShrink {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/Shrinkable.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/Shrinkable.java new file mode 100644 index 00000000000..8bbe4ccbdda --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/Shrinkable.java @@ -0,0 +1,20 @@ +package org.checkerframework.checker.index.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * An expression of type {@code @Shrinkable} may be used to remove elements, e.g., by calling {@code + * remove()} or {@code clear()} on it. + * + * @checker_framework.manual #growonly-checker Grow-only Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({UnshrinkableRef.class}) +public @interface Shrinkable {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/UncheckedShrinkable.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/UncheckedShrinkable.java new file mode 100644 index 00000000000..cbd4acc669e --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/UncheckedShrinkable.java @@ -0,0 +1,28 @@ +package org.checkerframework.checker.index.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * An expression of type {@code @UncheckedShrinkable} may be used to remove elements, e.g., by + * calling {@code remove()} or {@code clear()} on it. + * + *

      The Index Checker does not issue warnings about possible {@code IndexOutOfBoundsException}s + * when the collection has type {@code UncheckedShrinkable}. + * + *

      Thus, {@code @UncheckedShrinkable} is combination of {@code @}{@link Shrinkable} and a warning + * suppression. It is particularly useful when first annotating a codebase, to temporarily suppress + * some warnings while focusing on others. + * + * @checker_framework.manual #index-checker Index Checker + * @checker_framework.manual #growonly-checker Grow-only Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({Shrinkable.class}) +public @interface UncheckedShrinkable {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/UnshrinkableRef.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/UnshrinkableRef.java new file mode 100644 index 00000000000..cb05e97a548 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/UnshrinkableRef.java @@ -0,0 +1,25 @@ +package org.checkerframework.checker.index.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.InvisibleQualifier; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * An expression of type {@code @UnshrinkableRef} may not be used to remove elements, e.g., by + * calling {@code remove()} or {@code clear()} on it. The collection might be shrunk by some other + * reference that aliases the expression of type {@code @UnshrinkableRef}. + * + * @checker_framework.manual #growonly-checker Grow-only Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({}) +@DefaultQualifierInHierarchy +@InvisibleQualifier +public @interface UnshrinkableRef {} From d9252f5ed50f279b2bfcf6eff5a1c3f0206862b7 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 13 Nov 2025 16:54:02 -0800 Subject: [PATCH 22/82] Move `azure-pipelines.yml` into a subdirectory --- azure-pipelines.yml => .azure/azure-pipelines.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename azure-pipelines.yml => .azure/azure-pipelines.yml (100%) diff --git a/azure-pipelines.yml b/.azure/azure-pipelines.yml similarity index 100% rename from azure-pipelines.yml rename to .azure/azure-pipelines.yml From df696157dac514cf9a8d39e4d6e1e471824964a5 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 13 Nov 2025 19:04:38 -0800 Subject: [PATCH 23/82] Generate `azure-pipelines.yml` via m4 --- .azure/Makefile | 9 ++ .azure/azure-pipelines.yml | 43 ++++++- .azure/azure-pipelines.yml.m4 | 121 ++++++++++++++++++++ .azure/defs.m4 | 204 ++++++++++++++++++++++++++++++++++ 4 files changed, 372 insertions(+), 5 deletions(-) create mode 100644 .azure/Makefile create mode 100644 .azure/azure-pipelines.yml.m4 create mode 100644 .azure/defs.m4 diff --git a/.azure/Makefile b/.azure/Makefile new file mode 100644 index 00000000000..8032512f759 --- /dev/null +++ b/.azure/Makefile @@ -0,0 +1,9 @@ +all default: azure-pipelines.yml + +%: %.m4 defs.m4 + @chmod -f +w $@ || true + m4 $< > $@ + @chmod -w $@ + +clean: + rm -f azure-pipelines.yml diff --git a/.azure/azure-pipelines.yml b/.azure/azure-pipelines.yml index a1cfd12516f..fee7502c895 100644 --- a/.azure/azure-pipelines.yml +++ b/.azure/azure-pipelines.yml @@ -1,3 +1,9 @@ +# DO NOT EDIT azure-pipelines.yml. Edit azure-pipelines.yml.m4 and defs.m4 instead. + + + + + variables: system.debug: true @@ -42,14 +48,14 @@ jobs: displayName: show environment - bash: | set -ex - if [ -d /tmp/$USER/git-scripts ]; \ + if test -d /tmp/$USER/git-scripts ; \ then git -C /tmp/$USER/git-scripts pull -q > /dev/null 2>&1 ; \ else mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git ; \ fi displayName: git-scripts - bash: | set -ex - if [ -d /tmp/$USER/plume-scripts ]; \ + if test -d /tmp/$USER/plume-scripts ; \ then git -C /tmp/$USER/plume-scripts pull -q > /dev/null 2>&1 ; \ else mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/plume-scripts.git ; \ fi @@ -80,7 +86,7 @@ jobs: git config --global pull.rebase false git config --global core.longpaths true git config --global core.protectNTFS false - eval `/tmp/$USER/plume-scripts/ci-info typetools` + eval $(/tmp/$USER/plume-scripts/ci-info typetools) cd ../jdk17u && git status echo "About to run: git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH}" cd ../jdk17u && git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH} || (git --version && git show && git status && echo "Merge failed; see 'Pull request merge conflicts' at https://github.com/typetools/jdk/blob/master/README.md" && false) @@ -156,6 +162,14 @@ jobs: displayName: test-cftests-inference.sh - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh) displayName: test-typecheck.sh +## Here is how to create artifacts that can be downloaded. +# - bash: (cd ../checker-framework/checker/build/jtregJdk17/ && tar -czvf all.tgz all) +# condition: succeededOrFailed() +# displayName: tar jtregJdk17/all +# - publish: $(System.DefaultWorkingDirectory)/../checker-framework/checker/build/jtregJdk17/all.tgz +# artifact: all.tgz +# condition: failed() +# displayName: publish all.tgz - job: test_cftests_all_jdk21 timeoutInMinutes: 120 @@ -169,8 +183,26 @@ jobs: displayName: clone git-scripts - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework displayName: clone checker-framework - - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh) - displayName: test-cftests-all.sh +# test-cftests-all.sh sometimes runs out of memory (under JDK 11 and 17), but running its component parts in sequence does not. +# - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh) +# displayName: test-cftests-all.sh + - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh) + displayName: test-cftests-junit.sh + - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh) + displayName: test-cftests-nonjunit.sh + - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh) + displayName: test-cftests-inference.sh + - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh) + displayName: test-typecheck.sh +## Here is how to create artifacts that can be downloaded. +# - bash: (cd ../checker-framework/checker/build/jtregJdk21/ && tar -czvf all.tgz all) +# condition: succeededOrFailed() +# displayName: tar jtregJdk21/all +# - publish: $(System.DefaultWorkingDirectory)/../checker-framework/checker/build/jtregJdk21/all.tgz +# artifact: all.tgz +# condition: failed() +# displayName: publish all.tgz + - job: test_daikon pool: @@ -200,3 +232,4 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-plume-lib.sh) displayName: test-plume-lib.sh + diff --git a/.azure/azure-pipelines.yml.m4 b/.azure/azure-pipelines.yml.m4 new file mode 100644 index 00000000000..c910f4fd917 --- /dev/null +++ b/.azure/azure-pipelines.yml.m4 @@ -0,0 +1,121 @@ +# DO NOT EDIT azure-pipelines.yml. Edit azure-pipelines.yml.m4 and defs.m4 instead. + +changequote +changequote(`[',`]')dnl +include([defs.m4])dnl +variables: + system.debug: true + +jobs: + +- job: build_jdk + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk17-plus:latest + steps: + - bash: | + whoami + git config --get remote.origin.url + pwd + ls -al + env | sort + displayName: show environment + - bash: pwd && ls && bash ./configure --with-jtreg=/usr/share/jtreg --disable-warnings-as-errors + displayName: configure + - bash: make jdk + timeoutInMinutes: 90 + displayName: make jdk + ## This works only after `make images` + # - bash: build/*/images/jdk/bin/java -version + # displayName: version + ## Don't run tests, which pass only with old version of tools (compilers, etc.). + # - bash: make -C /jdk run-test-tier1 + # displayName: make run-test-tier1 + +- job: build_jdk17u + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk17-plus:latest + timeoutInMinutes: 0 + steps: + - bash: | + whoami + git config --get remote.origin.url + pwd + ls -al + env | sort + displayName: show environment + - bash: | + set -ex + if test -d /tmp/$USER/git-scripts ; \ + then git -C /tmp/$USER/git-scripts pull -q > /dev/null 2>&1 ; \ + else mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git ; \ + fi + displayName: git-scripts + - bash: | + set -ex + if test -d /tmp/$USER/plume-scripts ; \ + then git -C /tmp/$USER/plume-scripts pull -q > /dev/null 2>&1 ; \ + else mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/plume-scripts.git ; \ + fi + displayName: plume-scripts + # This creates ../jdk17u . + # If the depth is too small, the merge will fail. However, we cannot use "--filter=blob:none" + # because that leads to "fatal: remote error: filter 'combine' not supported". + - bash: | + set -ex + pwd + ls -al .. || true + ls -al ../jdk17u || true + df . + /tmp/$USER/git-scripts/git-clone-related typetools jdk17u ../jdk17u --depth 999 + git config --global user.email "you@example.com" + git config --global user.name "Your Name" + git config --global core.longpaths true + git config --global core.protectNTFS false + cd ../jdk17u && git status + git diff --exit-code + echo $? + displayName: clone-related-jdk17u + - bash: | + set -ex + git config --global user.email "you@example.com" + git config --global user.name "Your Name" + git config --global pull.ff true + git config --global pull.rebase false + git config --global core.longpaths true + git config --global core.protectNTFS false + eval $(/tmp/$USER/plume-scripts/ci-info typetools) + cd ../jdk17u && git status + echo "About to run: git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH}" + cd ../jdk17u && git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH} || (git --version && git show && git status && echo "Merge failed; see 'Pull request merge conflicts' at https://github.com/typetools/jdk/blob/master/README.md" && false) + displayName: git merge + - bash: cd ../jdk17u && export JT_HOME=/usr/share/jtreg && bash ./configure --with-jtreg --disable-warnings-as-errors + displayName: configure + - bash: cd ../jdk17u && make jdk + displayName: make jdk + ## This works only after `make images` + # - bash: cd ../jdk17u && build/*/images/jdk/bin/java -version + # displayName: version + # - bash: make -C /jdk17u run-test-tier1 + # timeoutInMinutes: 0 + # displayName: make run-test-tier1 + # - bash: make -C /jdk17u :test/jdk:tier1 + ## Temporarily comment out because of trouble finding junit and jasm + # - bash: cd ../jdk17u && make run-test TEST="jtreg:test/jdk:tier1" + # timeoutInMinutes: 0 + # displayName: make run-test + +cftests_all_job(11) +cftests_all_job(17) +cftests_all_job(21) + +daikon_job + +plume_lib_job(canary_version) + +ifelse([ +Local Variables: +eval: (add-hook 'after-save-hook '(lambda () (run-command nil "make")) nil 'local) +end: +])dnl diff --git a/.azure/defs.m4 b/.azure/defs.m4 new file mode 100644 index 00000000000..28743248917 --- /dev/null +++ b/.azure/defs.m4 @@ -0,0 +1,204 @@ +changequote +define(`LBRACKET',`[')dnl +define(`RBRACKET',`]')dnl +changequote(`[',`]')dnl +ifelse([The built-in "dnl" m4 macro means "discard to next line",])dnl +define([canary_os], [ubuntu])dnl +define([canary_version], [25])dnl +define([latest_version], [25])dnl +define([canary_test], [canary_os[]canary_version])dnl +define([docker_testing], [])dnl +ifelse([uncomment the next line to use the "testing" Docker images])dnl +ifelse([define([docker_testing], [-testing])])dnl +dnl +define([cftests_all_job], [dnl +- job: test_cftests_all_jdk$1 + timeoutInMinutes: 120 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk$1:latest + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework +# test-cftests-all.sh sometimes runs out of memory (under JDK 11 and 17), but running its component parts in sequence does not. +# - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh) +# displayName: test-cftests-all.sh + - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh) + displayName: test-cftests-junit.sh + - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh) + displayName: test-cftests-nonjunit.sh + - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh) + displayName: test-cftests-inference.sh + - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh) + displayName: test-typecheck.sh +## Here is how to create artifacts that can be downloaded. +# - bash: (cd ../checker-framework/checker/build/jtregJdk$1/ && tar -czvf all.tgz all) +# condition: succeededOrFailed() +# displayName: tar jtregJdk$1/all +# - publish: $(System.DefaultWorkingDirectory)/../checker-framework/checker/build/jtregJdk$1/all.tgz +# artifact: all.tgz +# condition: failed() +# displayName: publish all.tgz +]) + +define([junit_job], [dnl + - job: junit_jdk$1 +ifelse($1,canary_version,,[ dependsOn: + - canary_jobs + - junit_jdk[]canary_version +])dnl + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk$1[]docker_testing:latest + timeoutInMinutes: 70 + steps: + - checkout: self + fetchDepth: 25 + - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-cftests-junit.sh + displayName: test-cftests-junit.sh])dnl +dnl +define([nonjunit_job], [dnl + - job: nonjunit_jdk$1 +ifelse($1,canary_version,,[ dependsOn: + - canary_jobs + - nonjunit_jdk[]canary_version +])dnl + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk$1[]docker_testing:latest + steps: + - checkout: self + fetchDepth: 25 + - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-cftests-nonjunit.sh + displayName: test-cftests-nonjunit.sh])dnl +dnl +define([inference_job], [dnl +ifelse($1,canary_version,[dnl + # Split into part1 and part2 only for the inference job that "canary_jobs" depends on. + - job: inference_part1_jdk$1 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk$1[]docker_testing:latest + timeoutInMinutes: 90 + steps: + - checkout: self + fetchDepth: 25 + - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-cftests-inference-part1.sh + displayName: test-cftests-inference-part1.sh + - job: inference_part2_jdk$1 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk$1[]docker_testing:latest + timeoutInMinutes: 90 + steps: + - checkout: self + fetchDepth: 25 + - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-cftests-inference-part2.sh + displayName: test-cftests-inference-part2.sh +],[dnl + - job: inference_jdk$1 + dependsOn: + - canary_jobs + - inference_part1_jdk[]canary_version + - inference_part2_jdk[]canary_version + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk$1[]docker_testing:latest + timeoutInMinutes: 90 + steps: + - checkout: self + fetchDepth: 25 + - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-cftests-inference.sh + displayName: test-cftests-inference.sh +])dnl +])dnl +dnl +define([misc_job], [dnl + - job: misc_jdk$1 +ifelse($1,canary_version,,$1,latest_version,,[ dependsOn: + - canary_jobs + - misc_jdk[]canary_version +])dnl + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk$1-plus[]docker_testing:latest + steps: + - checkout: self + # Unlimited fetchDepth (0) for misc jobs, because of need to make contributors.tex. + fetchDepth: 0 + - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-misc.sh + displayName: test-misc.sh])dnl +dnl +define([typecheck_job], [dnl +ifelse($1,canary_version,[dnl + - job: typecheck_part1_jdk$1 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk$1[]docker_testing:latest + steps: + - checkout: self + fetchDepth: 1000 + - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-typecheck-part1.sh + displayName: test-typecheck-part1.sh + - job: typecheck_part2_jdk$1 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk$1[]docker_testing:latest + steps: + - checkout: self + fetchDepth: 1000 + - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-typecheck-part2.sh + displayName: test-typecheck-part2.sh], [dnl + - job: typecheck_jdk$1 + dependsOn: + - canary_jobs + - typecheck_part1_jdk[]canary_version + - typecheck_part2_jdk[]canary_version + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk$1[]docker_testing:latest + steps: + - checkout: self + fetchDepth: 1000 + - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-typecheck.sh + displayName: test-typecheck.sh])])dnl +dnl +define([daikon_job], [dnl +- job: test_daikon + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk17:latest + timeoutInMinutes: 70 + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework + - bash: (cd ../checker-framework && checker/bin-devel/test-daikon.sh) + displayName: test-daikon.sh])dnl +dnl +define([plume_lib_job], [dnl +- job: test_plume_lib + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk17:latest + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework + - bash: (cd ../checker-framework && checker/bin-devel/test-plume-lib.sh) + displayName: test-plume-lib.sh])dnl +ifelse([ +Local Variables: +eval: (add-hook 'after-save-hook '(lambda () (run-command nil "make")) nil 'local) +end: +])dnl From 9465dbc26283f6e3ad41a449fa522a1479665ea5 Mon Sep 17 00:00:00 2001 From: Suzanne Millstein Date: Fri, 14 Nov 2025 09:06:18 -0800 Subject: [PATCH 24/82] Split daikon test (#236) --- .azure/azure-pipelines.yml | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/.azure/azure-pipelines.yml b/.azure/azure-pipelines.yml index fee7502c895..8deef72867e 100644 --- a/.azure/azure-pipelines.yml +++ b/.azure/azure-pipelines.yml @@ -204,7 +204,7 @@ jobs: # displayName: publish all.tgz -- job: test_daikon +- job: test_daikon_part1 pool: vmImage: 'ubuntu-latest' container: mdernst/cf-ubuntu-jdk17:latest @@ -216,8 +216,38 @@ jobs: displayName: clone git-scripts - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework displayName: clone checker-framework - - bash: (cd ../checker-framework && checker/bin-devel/test-daikon.sh) - displayName: test-daikon.sh + - bash: (cd ../checker-framework && checker/bin-devel/test-daikon-part1.sh) + displayName: test-daikon-part1.sh + +- job: test_daikon_part2 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk17:latest + timeoutInMinutes: 70 + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework + - bash: (cd ../checker-framework && checker/bin-devel/test-daikon-part2.sh) + displayName: test-daikon-part2.sh + +- job: test_daikon_part3 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk17:latest + timeoutInMinutes: 70 + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework + - bash: (cd ../checker-framework && checker/bin-devel/test-daikon-part3.sh) + displayName: test-daikon-part3.sh - job: test_plume_lib pool: From a3a0f02324abc6515f18bbde9e787b9e816844c3 Mon Sep 17 00:00:00 2001 From: Suzanne Millstein Date: Fri, 14 Nov 2025 09:46:38 -0800 Subject: [PATCH 25/82] Improve documentation of jdk17u repository --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c1bef843fce..ce91a26266c 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,7 @@ Make changes in the `typetools/jdk` repository. (Note that this README file appears in both the `typetools/jdk` and `typetools/jdk17u` repositories!) To update jdk17u from its upstreams: +(These are the only edits to jdk17u allowed, plus changes needed to resolve merge conflicts.) ``` cd jdk17u git pull From 01eafb2340d5615656844be5c21d80e7214020b6 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 14 Nov 2025 13:27:03 -0800 Subject: [PATCH 26/82] Split cftests_all job --- .azure/azure-pipelines.yml | 208 +++++++++++++++++++++++++++------- .azure/azure-pipelines.yml.m4 | 19 +++- .azure/defs.m4 | 30 +---- 3 files changed, 189 insertions(+), 68 deletions(-) diff --git a/.azure/azure-pipelines.yml b/.azure/azure-pipelines.yml index 8deef72867e..f218a2f7c9a 100644 --- a/.azure/azure-pipelines.yml +++ b/.azure/azure-pipelines.yml @@ -2,8 +2,6 @@ - - variables: system.debug: true @@ -107,7 +105,7 @@ jobs: # timeoutInMinutes: 0 # displayName: make run-test -- job: test_cftests_all_jdk11 +- job: test_cftests_junit_jdk11 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -119,27 +117,51 @@ jobs: displayName: clone git-scripts - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework displayName: clone checker-framework -# test-cftests-all.sh sometimes runs out of memory (under JDK 11 and 17), but running its component parts in sequence does not. -# - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh) -# displayName: test-cftests-all.sh - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh) displayName: test-cftests-junit.sh +- job: test_cftests_nonjunit_jdk11 + timeoutInMinutes: 120 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk11:latest + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh) displayName: test-cftests-nonjunit.sh +- job: test_cftests_inference_jdk11 + timeoutInMinutes: 120 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk11:latest + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh) displayName: test-cftests-inference.sh +- job: test_cftests_typecheck_jdk11 + timeoutInMinutes: 120 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk11:latest + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh) displayName: test-typecheck.sh -## Here is how to create artifacts that can be downloaded. -# - bash: (cd ../checker-framework/checker/build/jtregJdk11/ && tar -czvf all.tgz all) -# condition: succeededOrFailed() -# displayName: tar jtregJdk11/all -# - publish: $(System.DefaultWorkingDirectory)/../checker-framework/checker/build/jtregJdk11/all.tgz -# artifact: all.tgz -# condition: failed() -# displayName: publish all.tgz - -- job: test_cftests_all_jdk17 +- job: test_cftests_junit_jdk17 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -151,27 +173,79 @@ jobs: displayName: clone git-scripts - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework displayName: clone checker-framework -# test-cftests-all.sh sometimes runs out of memory (under JDK 11 and 17), but running its component parts in sequence does not. -# - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh) -# displayName: test-cftests-all.sh - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh) displayName: test-cftests-junit.sh +- job: test_cftests_nonjunit_jdk17 + timeoutInMinutes: 120 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk17:latest + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh) displayName: test-cftests-nonjunit.sh +- job: test_cftests_inference_jdk17 + timeoutInMinutes: 120 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk17:latest + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh) displayName: test-cftests-inference.sh +- job: test_cftests_typecheck_jdk17 + timeoutInMinutes: 120 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk17:latest + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh) displayName: test-typecheck.sh -## Here is how to create artifacts that can be downloaded. -# - bash: (cd ../checker-framework/checker/build/jtregJdk17/ && tar -czvf all.tgz all) -# condition: succeededOrFailed() -# displayName: tar jtregJdk17/all -# - publish: $(System.DefaultWorkingDirectory)/../checker-framework/checker/build/jtregJdk17/all.tgz -# artifact: all.tgz -# condition: failed() -# displayName: publish all.tgz - -- job: test_cftests_all_jdk21 +- job: test_cftests_junit_jdk21 + timeoutInMinutes: 120 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk21:latest + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework + - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh) + displayName: test-cftests-junit.sh +- job: test_cftests_nonjunit_jdk21 + timeoutInMinutes: 120 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk21:latest + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework + - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh) + displayName: test-cftests-nonjunit.sh +- job: test_cftests_inference_jdk21 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -183,26 +257,78 @@ jobs: displayName: clone git-scripts - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework displayName: clone checker-framework -# test-cftests-all.sh sometimes runs out of memory (under JDK 11 and 17), but running its component parts in sequence does not. -# - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh) -# displayName: test-cftests-all.sh + - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh) + displayName: test-cftests-inference.sh +- job: test_cftests_typecheck_jdk21 + timeoutInMinutes: 120 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk21:latest + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework + - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh) + displayName: test-typecheck.sh +- job: test_cftests_junit_jdk25 + timeoutInMinutes: 120 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk25:latest + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh) displayName: test-cftests-junit.sh +- job: test_cftests_nonjunit_jdk25 + timeoutInMinutes: 120 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk25:latest + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh) displayName: test-cftests-nonjunit.sh +- job: test_cftests_inference_jdk25 + timeoutInMinutes: 120 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk25:latest + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh) displayName: test-cftests-inference.sh +- job: test_cftests_typecheck_jdk25 + timeoutInMinutes: 120 + pool: + vmImage: 'ubuntu-latest' + container: mdernst/cf-ubuntu-jdk25:latest + steps: + - checkout: self + fetchDepth: 25 + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git + displayName: clone git-scripts + - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework + displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh) displayName: test-typecheck.sh -## Here is how to create artifacts that can be downloaded. -# - bash: (cd ../checker-framework/checker/build/jtregJdk21/ && tar -czvf all.tgz all) -# condition: succeededOrFailed() -# displayName: tar jtregJdk21/all -# - publish: $(System.DefaultWorkingDirectory)/../checker-framework/checker/build/jtregJdk21/all.tgz -# artifact: all.tgz -# condition: failed() -# displayName: publish all.tgz - - job: test_daikon_part1 pool: diff --git a/.azure/azure-pipelines.yml.m4 b/.azure/azure-pipelines.yml.m4 index c910f4fd917..a16d6af702f 100644 --- a/.azure/azure-pipelines.yml.m4 +++ b/.azure/azure-pipelines.yml.m4 @@ -106,9 +106,22 @@ jobs: # timeoutInMinutes: 0 # displayName: make run-test -cftests_all_job(11) -cftests_all_job(17) -cftests_all_job(21) +cftests_job(junit, cftests-junit, 11) +cftests_job(nonjunit, cftests-nonjunit, 11) +cftests_job(inference, cftests-inference, 11) +cftests_job(typecheck, typecheck, 11) +cftests_job(junit, cftests-junit, 17) +cftests_job(nonjunit, cftests-nonjunit, 17) +cftests_job(inference, cftests-inference, 17) +cftests_job(typecheck, typecheck, 17) +cftests_job(junit, cftests-junit, 21) +cftests_job(nonjunit, cftests-nonjunit, 21) +cftests_job(inference, cftests-inference, 21) +cftests_job(typecheck, typecheck, 21) +cftests_job(junit, cftests-junit, 25) +cftests_job(nonjunit, cftests-nonjunit, 25) +cftests_job(inference, cftests-inference, 25) +cftests_job(typecheck, typecheck, 25) daikon_job diff --git a/.azure/defs.m4 b/.azure/defs.m4 index 28743248917..ccc967bed9f 100644 --- a/.azure/defs.m4 +++ b/.azure/defs.m4 @@ -11,12 +11,12 @@ define([docker_testing], [])dnl ifelse([uncomment the next line to use the "testing" Docker images])dnl ifelse([define([docker_testing], [-testing])])dnl dnl -define([cftests_all_job], [dnl -- job: test_cftests_all_jdk$1 +define([cftests_job], [dnl +- job: test_cftests_$1_jdk$3 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' - container: mdernst/cf-ubuntu-jdk$1:latest + container: mdernst/cf-ubuntu-jdk$3:latest steps: - checkout: self fetchDepth: 25 @@ -24,27 +24,9 @@ define([cftests_all_job], [dnl displayName: clone git-scripts - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework displayName: clone checker-framework -# test-cftests-all.sh sometimes runs out of memory (under JDK 11 and 17), but running its component parts in sequence does not. -# - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh) -# displayName: test-cftests-all.sh - - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh) - displayName: test-cftests-junit.sh - - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh) - displayName: test-cftests-nonjunit.sh - - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh) - displayName: test-cftests-inference.sh - - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh) - displayName: test-typecheck.sh -## Here is how to create artifacts that can be downloaded. -# - bash: (cd ../checker-framework/checker/build/jtregJdk$1/ && tar -czvf all.tgz all) -# condition: succeededOrFailed() -# displayName: tar jtregJdk$1/all -# - publish: $(System.DefaultWorkingDirectory)/../checker-framework/checker/build/jtregJdk$1/all.tgz -# artifact: all.tgz -# condition: failed() -# displayName: publish all.tgz -]) - + - bash: (cd ../checker-framework && checker/bin-devel/test-$2.sh) + displayName: test-$2.sh])dnl +dnl define([junit_job], [dnl - job: junit_jdk$1 ifelse($1,canary_version,,[ dependsOn: From 37cb08f992f682f6ac1fc91d80b5fce0ed2b4bf2 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 14 Nov 2025 15:03:42 -0800 Subject: [PATCH 27/82] Generate Daikon jobs --- .azure/azure-pipelines.yml | 2 -- .azure/azure-pipelines.yml.m4 | 4 +++- .azure/defs.m4 | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.azure/azure-pipelines.yml b/.azure/azure-pipelines.yml index f218a2f7c9a..4f22eb29b78 100644 --- a/.azure/azure-pipelines.yml +++ b/.azure/azure-pipelines.yml @@ -344,7 +344,6 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-daikon-part1.sh) displayName: test-daikon-part1.sh - - job: test_daikon_part2 pool: vmImage: 'ubuntu-latest' @@ -359,7 +358,6 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-daikon-part2.sh) displayName: test-daikon-part2.sh - - job: test_daikon_part3 pool: vmImage: 'ubuntu-latest' diff --git a/.azure/azure-pipelines.yml.m4 b/.azure/azure-pipelines.yml.m4 index a16d6af702f..231ad5c5cd9 100644 --- a/.azure/azure-pipelines.yml.m4 +++ b/.azure/azure-pipelines.yml.m4 @@ -123,7 +123,9 @@ cftests_job(nonjunit, cftests-nonjunit, 25) cftests_job(inference, cftests-inference, 25) cftests_job(typecheck, typecheck, 25) -daikon_job +daikon_job(1) +daikon_job(2) +daikon_job(3) plume_lib_job(canary_version) diff --git a/.azure/defs.m4 b/.azure/defs.m4 index ccc967bed9f..090da411788 100644 --- a/.azure/defs.m4 +++ b/.azure/defs.m4 @@ -150,7 +150,7 @@ ifelse($1,canary_version,[dnl displayName: test-typecheck.sh])])dnl dnl define([daikon_job], [dnl -- job: test_daikon +- job: test_daikon_part$1 pool: vmImage: 'ubuntu-latest' container: mdernst/cf-ubuntu-jdk17:latest @@ -162,8 +162,8 @@ define([daikon_job], [dnl displayName: clone git-scripts - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework displayName: clone checker-framework - - bash: (cd ../checker-framework && checker/bin-devel/test-daikon.sh) - displayName: test-daikon.sh])dnl + - bash: (cd ../checker-framework && checker/bin-devel/test-daikon-part$1.sh) + displayName: test-daikon-part$1.sh])dnl dnl define([plume_lib_job], [dnl - job: test_plume_lib From 461b07bc828a0330e41baa8037492a9122c7da57 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sat, 15 Nov 2025 20:50:20 -0800 Subject: [PATCH 28/82] Shorten job names --- .azure/azure-pipelines.yml | 32 ++++++++++++++++---------------- .azure/defs.m4 | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.azure/azure-pipelines.yml b/.azure/azure-pipelines.yml index 4f22eb29b78..518cb7f3bbd 100644 --- a/.azure/azure-pipelines.yml +++ b/.azure/azure-pipelines.yml @@ -105,7 +105,7 @@ jobs: # timeoutInMinutes: 0 # displayName: make run-test -- job: test_cftests_junit_jdk11 +- job: cftests_junit_jdk11 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -119,7 +119,7 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh) displayName: test-cftests-junit.sh -- job: test_cftests_nonjunit_jdk11 +- job: cftests_nonjunit_jdk11 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -133,7 +133,7 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh) displayName: test-cftests-nonjunit.sh -- job: test_cftests_inference_jdk11 +- job: cftests_inference_jdk11 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -147,7 +147,7 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh) displayName: test-cftests-inference.sh -- job: test_cftests_typecheck_jdk11 +- job: cftests_typecheck_jdk11 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -161,7 +161,7 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh) displayName: test-typecheck.sh -- job: test_cftests_junit_jdk17 +- job: cftests_junit_jdk17 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -175,7 +175,7 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh) displayName: test-cftests-junit.sh -- job: test_cftests_nonjunit_jdk17 +- job: cftests_nonjunit_jdk17 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -189,7 +189,7 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh) displayName: test-cftests-nonjunit.sh -- job: test_cftests_inference_jdk17 +- job: cftests_inference_jdk17 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -203,7 +203,7 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh) displayName: test-cftests-inference.sh -- job: test_cftests_typecheck_jdk17 +- job: cftests_typecheck_jdk17 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -217,7 +217,7 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh) displayName: test-typecheck.sh -- job: test_cftests_junit_jdk21 +- job: cftests_junit_jdk21 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -231,7 +231,7 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh) displayName: test-cftests-junit.sh -- job: test_cftests_nonjunit_jdk21 +- job: cftests_nonjunit_jdk21 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -245,7 +245,7 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh) displayName: test-cftests-nonjunit.sh -- job: test_cftests_inference_jdk21 +- job: cftests_inference_jdk21 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -259,7 +259,7 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh) displayName: test-cftests-inference.sh -- job: test_cftests_typecheck_jdk21 +- job: cftests_typecheck_jdk21 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -273,7 +273,7 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh) displayName: test-typecheck.sh -- job: test_cftests_junit_jdk25 +- job: cftests_junit_jdk25 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -287,7 +287,7 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh) displayName: test-cftests-junit.sh -- job: test_cftests_nonjunit_jdk25 +- job: cftests_nonjunit_jdk25 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -301,7 +301,7 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh) displayName: test-cftests-nonjunit.sh -- job: test_cftests_inference_jdk25 +- job: cftests_inference_jdk25 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' @@ -315,7 +315,7 @@ jobs: displayName: clone checker-framework - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh) displayName: test-cftests-inference.sh -- job: test_cftests_typecheck_jdk25 +- job: cftests_typecheck_jdk25 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' diff --git a/.azure/defs.m4 b/.azure/defs.m4 index 090da411788..1d651873c28 100644 --- a/.azure/defs.m4 +++ b/.azure/defs.m4 @@ -12,7 +12,7 @@ ifelse([uncomment the next line to use the "testing" Docker images])dnl ifelse([define([docker_testing], [-testing])])dnl dnl define([cftests_job], [dnl -- job: test_cftests_$1_jdk$3 +- job: cftests_$1_jdk$3 timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' From 2d478748182be9384580565fed99847f83f61337 Mon Sep 17 00:00:00 2001 From: Suzanne Millstein Date: Wed, 19 Nov 2025 10:38:57 -0800 Subject: [PATCH 29/82] Annotated io/nio/concurrent exceptions (#244) Co-authored-by: Davy Landman --- src/java.base/share/classes/java/io/EOFException.java | 6 +++++- .../share/classes/java/io/FileNotFoundException.java | 7 +++++-- src/java.base/share/classes/java/io/IOError.java | 5 ++++- .../share/classes/java/io/NotActiveException.java | 6 +++++- .../classes/java/io/NotSerializableException.java | 6 +++++- .../share/classes/java/io/OptionalDataException.java | 3 +++ .../classes/java/io/StreamCorruptedException.java | 5 ++++- .../share/classes/java/io/SyncFailedException.java | 6 +++++- .../share/classes/java/io/UTFDataFormatException.java | 6 +++++- .../classes/java/io/UnsupportedEncodingException.java | 6 +++++- .../share/classes/java/io/WriteAbortedException.java | 6 ++++-- .../classes/java/nio/file/AccessDeniedException.java | 9 ++++++--- .../java/nio/file/AtomicMoveNotSupportedException.java | 10 +++++++--- .../java/nio/file/DirectoryIteratorException.java | 4 ++++ .../java/nio/file/DirectoryNotEmptyException.java | 5 ++++- .../java/nio/file/FileAlreadyExistsException.java | 8 ++++++-- .../nio/file/FileSystemAlreadyExistsException.java | 6 +++++- .../classes/java/nio/file/FileSystemLoopException.java | 6 +++++- .../java/nio/file/FileSystemNotFoundException.java | 6 +++++- .../classes/java/nio/file/InvalidPathException.java | 3 +++ .../classes/java/nio/file/NoSuchFileException.java | 8 ++++++-- .../classes/java/nio/file/NotDirectoryException.java | 6 +++++- .../share/classes/java/nio/file/NotLinkException.java | 8 ++++++-- .../java/nio/file/ProviderMismatchException.java | 6 +++++- .../java/nio/file/ProviderNotFoundException.java | 6 +++++- .../java/nio/file/ReadOnlyFileSystemException.java | 3 +++ .../java/util/concurrent/BrokenBarrierException.java | 6 +++++- .../java/util/concurrent/CompletionException.java | 10 +++++++--- .../util/concurrent/RejectedExecutionException.java | 10 +++++++--- 29 files changed, 144 insertions(+), 38 deletions(-) diff --git a/src/java.base/share/classes/java/io/EOFException.java b/src/java.base/share/classes/java/io/EOFException.java index dcc1315e762..ab2b9a86ba1 100644 --- a/src/java.base/share/classes/java/io/EOFException.java +++ b/src/java.base/share/classes/java/io/EOFException.java @@ -25,6 +25,9 @@ package java.io; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Signals that an end of file or end of stream has been reached * unexpectedly during input. @@ -38,6 +41,7 @@ * @see java.io.IOException * @since 1.0 */ +@AnnotatedFor({"nullness"}) public class EOFException extends IOException { @java.io.Serial private static final long serialVersionUID = 6433858223774886977L; @@ -58,7 +62,7 @@ public EOFException() { * * @param s the detail message. */ - public EOFException(String s) { + public EOFException(@Nullable String s) { super(s); } } diff --git a/src/java.base/share/classes/java/io/FileNotFoundException.java b/src/java.base/share/classes/java/io/FileNotFoundException.java index 8d13aa3fdb9..331447c4d7b 100644 --- a/src/java.base/share/classes/java/io/FileNotFoundException.java +++ b/src/java.base/share/classes/java/io/FileNotFoundException.java @@ -25,6 +25,8 @@ package java.io; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; /** * Signals that an attempt to open the file denoted by a specified pathname @@ -39,6 +41,7 @@ * @since 1.0 */ +@AnnotatedFor({"nullness"}) public class FileNotFoundException extends IOException { @java.io.Serial private static final long serialVersionUID = -897856973823710492L; @@ -60,7 +63,7 @@ public FileNotFoundException() { * * @param s the detail message. */ - public FileNotFoundException(String s) { + public FileNotFoundException(@Nullable String s) { super(s); } @@ -73,7 +76,7 @@ public FileNotFoundException(String s) { * * @since 1.2 */ - private FileNotFoundException(String path, String reason) { + private FileNotFoundException(String path, @Nullable String reason) { super(path + ((reason == null) ? "" : " (" + reason + ")")); diff --git a/src/java.base/share/classes/java/io/IOError.java b/src/java.base/share/classes/java/io/IOError.java index 622143db9a8..1d6e6fbe2ab 100644 --- a/src/java.base/share/classes/java/io/IOError.java +++ b/src/java.base/share/classes/java/io/IOError.java @@ -25,12 +25,15 @@ package java.io; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; /** * Thrown when a serious I/O error has occurred. * * @author Xueming Shen * @since 1.6 */ +@AnnotatedFor({"nullness"}) public class IOError extends Error { /** * Constructs a new instance of IOError with the specified cause. The @@ -42,7 +45,7 @@ public class IOError extends Error { * The cause of this error, or {@code null} if the cause * is not known */ - public IOError(Throwable cause) { + public IOError(@Nullable Throwable cause) { super(cause); } diff --git a/src/java.base/share/classes/java/io/NotActiveException.java b/src/java.base/share/classes/java/io/NotActiveException.java index 3b8b281cbf4..7835518fdd0 100644 --- a/src/java.base/share/classes/java/io/NotActiveException.java +++ b/src/java.base/share/classes/java/io/NotActiveException.java @@ -25,11 +25,15 @@ package java.io; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Thrown when serialization or deserialization is not active. * * @since 1.1 */ +@AnnotatedFor({"nullness"}) public class NotActiveException extends ObjectStreamException { @java.io.Serial @@ -40,7 +44,7 @@ public class NotActiveException extends ObjectStreamException { * * @param reason a String describing the reason for the exception. */ - public NotActiveException(String reason) { + public NotActiveException(@Nullable String reason) { super(reason); } diff --git a/src/java.base/share/classes/java/io/NotSerializableException.java b/src/java.base/share/classes/java/io/NotSerializableException.java index d1010188272..a660b09e233 100644 --- a/src/java.base/share/classes/java/io/NotSerializableException.java +++ b/src/java.base/share/classes/java/io/NotSerializableException.java @@ -25,6 +25,9 @@ package java.io; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Thrown when an instance is required to have a Serializable interface. * The serialization runtime or the class of the instance can throw @@ -32,6 +35,7 @@ * * @since 1.1 */ +@AnnotatedFor({"nullness"}) public class NotSerializableException extends ObjectStreamException { @java.io.Serial @@ -42,7 +46,7 @@ public class NotSerializableException extends ObjectStreamException { * * @param classname Class of the instance being serialized/deserialized. */ - public NotSerializableException(String classname) { + public NotSerializableException(@Nullable String classname) { super(classname); } diff --git a/src/java.base/share/classes/java/io/OptionalDataException.java b/src/java.base/share/classes/java/io/OptionalDataException.java index f98bf079e8e..e62169b36fd 100644 --- a/src/java.base/share/classes/java/io/OptionalDataException.java +++ b/src/java.base/share/classes/java/io/OptionalDataException.java @@ -24,6 +24,8 @@ */ package java.io; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Exception indicating the failure of an object read operation due to * unread primitive data, or the end of data belonging to a serialized @@ -44,6 +46,7 @@ * * @since 1.1 */ +@AnnotatedFor({"nullness"}) public class OptionalDataException extends ObjectStreamException { @java.io.Serial diff --git a/src/java.base/share/classes/java/io/StreamCorruptedException.java b/src/java.base/share/classes/java/io/StreamCorruptedException.java index 5124c5ce657..408443f8a5b 100644 --- a/src/java.base/share/classes/java/io/StreamCorruptedException.java +++ b/src/java.base/share/classes/java/io/StreamCorruptedException.java @@ -25,12 +25,15 @@ package java.io; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; /** * Thrown when control information that was read from an object stream * violates internal consistency checks. * * @since 1.1 */ +@AnnotatedFor({"nullness"}) public class StreamCorruptedException extends ObjectStreamException { @java.io.Serial @@ -41,7 +44,7 @@ public class StreamCorruptedException extends ObjectStreamException { * * @param reason String describing the reason for the exception. */ - public StreamCorruptedException(String reason) { + public StreamCorruptedException(@Nullable String reason) { super(reason); } diff --git a/src/java.base/share/classes/java/io/SyncFailedException.java b/src/java.base/share/classes/java/io/SyncFailedException.java index e940b5a7e56..aedabf3add3 100644 --- a/src/java.base/share/classes/java/io/SyncFailedException.java +++ b/src/java.base/share/classes/java/io/SyncFailedException.java @@ -25,6 +25,9 @@ package java.io; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Signals that a sync operation has failed. * @@ -33,6 +36,7 @@ * @see java.io.IOException * @since 1.1 */ +@AnnotatedFor({"nullness"}) public class SyncFailedException extends IOException { @java.io.Serial private static final long serialVersionUID = -2353342684412443330L; @@ -43,7 +47,7 @@ public class SyncFailedException extends IOException { * * @param desc a String describing the exception. */ - public SyncFailedException(String desc) { + public SyncFailedException(@Nullable String desc) { super(desc); } } diff --git a/src/java.base/share/classes/java/io/UTFDataFormatException.java b/src/java.base/share/classes/java/io/UTFDataFormatException.java index bb8eb3b7d81..cc45ea2d3d3 100644 --- a/src/java.base/share/classes/java/io/UTFDataFormatException.java +++ b/src/java.base/share/classes/java/io/UTFDataFormatException.java @@ -25,6 +25,9 @@ package java.io; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Signals that a malformed string in * modified UTF-8 @@ -42,6 +45,7 @@ * @see java.io.IOException * @since 1.0 */ +@AnnotatedFor({"nullness"}) public class UTFDataFormatException extends IOException { @java.io.Serial private static final long serialVersionUID = 420743449228280612L; @@ -63,7 +67,7 @@ public UTFDataFormatException() { * * @param s the detail message. */ - public UTFDataFormatException(String s) { + public UTFDataFormatException(@Nullable String s) { super(s); } } diff --git a/src/java.base/share/classes/java/io/UnsupportedEncodingException.java b/src/java.base/share/classes/java/io/UnsupportedEncodingException.java index b80f453f5c6..48440f8ae19 100644 --- a/src/java.base/share/classes/java/io/UnsupportedEncodingException.java +++ b/src/java.base/share/classes/java/io/UnsupportedEncodingException.java @@ -24,12 +24,16 @@ */ package java.io; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * The Character Encoding is not supported. * * @author Asmus Freytag * @since 1.1 */ +@AnnotatedFor({"nullness"}) public class UnsupportedEncodingException extends IOException { @@ -47,7 +51,7 @@ public UnsupportedEncodingException() { * Constructs an UnsupportedEncodingException with a detail message. * @param s Describes the reason for the exception. */ - public UnsupportedEncodingException(String s) { + public UnsupportedEncodingException(@Nullable String s) { super(s); } } diff --git a/src/java.base/share/classes/java/io/WriteAbortedException.java b/src/java.base/share/classes/java/io/WriteAbortedException.java index a179d2d669c..c4f3ed55d31 100644 --- a/src/java.base/share/classes/java/io/WriteAbortedException.java +++ b/src/java.base/share/classes/java/io/WriteAbortedException.java @@ -26,6 +26,7 @@ package java.io; import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; /** * Signals that one of the ObjectStreamExceptions was thrown during a @@ -37,6 +38,7 @@ * * @since 1.1 */ +@AnnotatedFor({"nullness"}) public class WriteAbortedException extends ObjectStreamException { @java.io.Serial private static final long serialVersionUID = -3326426625597282442L; @@ -51,7 +53,7 @@ public class WriteAbortedException extends ObjectStreamException { * @serial */ @Deprecated(since="17") - public Exception detail; + public @Nullable Exception detail; /** * Constructs a WriteAbortedException with a string describing @@ -59,7 +61,7 @@ public class WriteAbortedException extends ObjectStreamException { * @param s String describing the exception. * @param ex Exception causing the abort. */ - public WriteAbortedException(String s, Exception ex) { + public WriteAbortedException(@Nullable String s, @Nullable Exception ex) { super(s); initCause(null); // Disallow subsequent initCause detail = ex; diff --git a/src/java.base/share/classes/java/nio/file/AccessDeniedException.java b/src/java.base/share/classes/java/nio/file/AccessDeniedException.java index 10f0fda3955..d45fca83c0b 100644 --- a/src/java.base/share/classes/java/nio/file/AccessDeniedException.java +++ b/src/java.base/share/classes/java/nio/file/AccessDeniedException.java @@ -25,6 +25,9 @@ package java.nio.file; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Checked exception thrown when a file system operation is denied, typically * due to a file permission or other access check. @@ -36,7 +39,7 @@ * * @since 1.7 */ - +@AnnotatedFor({"nullness"}) public class AccessDeniedException extends FileSystemException { @@ -49,7 +52,7 @@ public class AccessDeniedException * @param file * a string identifying the file or {@code null} if not known */ - public AccessDeniedException(String file) { + public AccessDeniedException(@Nullable String file) { super(file); } @@ -63,7 +66,7 @@ public AccessDeniedException(String file) { * @param reason * a reason message with additional information or {@code null} */ - public AccessDeniedException(String file, String other, String reason) { + public AccessDeniedException(@Nullable String file, @Nullable String other, @Nullable String reason) { super(file, other, reason); } } diff --git a/src/java.base/share/classes/java/nio/file/AtomicMoveNotSupportedException.java b/src/java.base/share/classes/java/nio/file/AtomicMoveNotSupportedException.java index e08ba0a343c..59a60350485 100644 --- a/src/java.base/share/classes/java/nio/file/AtomicMoveNotSupportedException.java +++ b/src/java.base/share/classes/java/nio/file/AtomicMoveNotSupportedException.java @@ -25,6 +25,9 @@ package java.nio.file; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Checked exception thrown when a file cannot be moved as an atomic file system * operation. @@ -32,6 +35,7 @@ * @since 1.7 */ +@AnnotatedFor({"nullness"}) public class AtomicMoveNotSupportedException extends FileSystemException { @@ -48,9 +52,9 @@ public class AtomicMoveNotSupportedException * @param reason * a reason message with additional information or {@code null} */ - public AtomicMoveNotSupportedException(String source, - String target, - String reason) + public AtomicMoveNotSupportedException(@Nullable String source, + @Nullable String target, + @Nullable String reason) { super(source, target, reason); } diff --git a/src/java.base/share/classes/java/nio/file/DirectoryIteratorException.java b/src/java.base/share/classes/java/nio/file/DirectoryIteratorException.java index 51fb08759e0..5944e3d4a4a 100644 --- a/src/java.base/share/classes/java/nio/file/DirectoryIteratorException.java +++ b/src/java.base/share/classes/java/nio/file/DirectoryIteratorException.java @@ -31,6 +31,9 @@ import java.io.ObjectInputStream; import java.io.InvalidObjectException; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Runtime exception thrown if an I/O error is encountered when iterating over * the entries in a directory. The I/O error is retrieved as an {@link @@ -40,6 +43,7 @@ * @see DirectoryStream */ +@AnnotatedFor({"nullness"}) public final class DirectoryIteratorException extends ConcurrentModificationException { diff --git a/src/java.base/share/classes/java/nio/file/DirectoryNotEmptyException.java b/src/java.base/share/classes/java/nio/file/DirectoryNotEmptyException.java index 563e0830f06..1dc2c7543ba 100644 --- a/src/java.base/share/classes/java/nio/file/DirectoryNotEmptyException.java +++ b/src/java.base/share/classes/java/nio/file/DirectoryNotEmptyException.java @@ -25,6 +25,8 @@ package java.nio.file; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; /** * Checked exception thrown when a file system operation fails because a * directory is not empty. @@ -32,6 +34,7 @@ * @since 1.7 */ +@AnnotatedFor({"nullness"}) public class DirectoryNotEmptyException extends FileSystemException { @@ -44,7 +47,7 @@ public class DirectoryNotEmptyException * @param dir * a string identifying the directory or {@code null} if not known */ - public DirectoryNotEmptyException(String dir) { + public DirectoryNotEmptyException(@Nullable String dir) { super(dir); } } diff --git a/src/java.base/share/classes/java/nio/file/FileAlreadyExistsException.java b/src/java.base/share/classes/java/nio/file/FileAlreadyExistsException.java index 90fcbba25be..0586d5e28f4 100644 --- a/src/java.base/share/classes/java/nio/file/FileAlreadyExistsException.java +++ b/src/java.base/share/classes/java/nio/file/FileAlreadyExistsException.java @@ -25,6 +25,9 @@ package java.nio.file; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Checked exception thrown when an attempt is made to create a file or * directory and a file of that name already exists. @@ -32,6 +35,7 @@ * @since 1.7 */ +@AnnotatedFor({"nullness"}) public class FileAlreadyExistsException extends FileSystemException { @@ -44,7 +48,7 @@ public class FileAlreadyExistsException * @param file * a string identifying the file or {@code null} if not known */ - public FileAlreadyExistsException(String file) { + public FileAlreadyExistsException(@Nullable String file) { super(file); } @@ -58,7 +62,7 @@ public FileAlreadyExistsException(String file) { * @param reason * a reason message with additional information or {@code null} */ - public FileAlreadyExistsException(String file, String other, String reason) { + public FileAlreadyExistsException(@Nullable String file, @Nullable String other, @Nullable String reason) { super(file, other, reason); } } diff --git a/src/java.base/share/classes/java/nio/file/FileSystemAlreadyExistsException.java b/src/java.base/share/classes/java/nio/file/FileSystemAlreadyExistsException.java index 0f4be9f393a..afa5750db97 100644 --- a/src/java.base/share/classes/java/nio/file/FileSystemAlreadyExistsException.java +++ b/src/java.base/share/classes/java/nio/file/FileSystemAlreadyExistsException.java @@ -25,6 +25,9 @@ package java.nio.file; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Runtime exception thrown when an attempt is made to create a file system that * already exists. @@ -32,6 +35,7 @@ * @since 1.7 */ +@AnnotatedFor({"nullness"}) public class FileSystemAlreadyExistsException extends RuntimeException { @@ -50,7 +54,7 @@ public FileSystemAlreadyExistsException() { * @param msg * the detail message */ - public FileSystemAlreadyExistsException(String msg) { + public FileSystemAlreadyExistsException(@Nullable String msg) { super(msg); } } diff --git a/src/java.base/share/classes/java/nio/file/FileSystemLoopException.java b/src/java.base/share/classes/java/nio/file/FileSystemLoopException.java index 0cea2e94abf..b0e0df2dd36 100644 --- a/src/java.base/share/classes/java/nio/file/FileSystemLoopException.java +++ b/src/java.base/share/classes/java/nio/file/FileSystemLoopException.java @@ -25,6 +25,9 @@ package java.nio.file; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Checked exception thrown when a file system loop, or cycle, is encountered. * @@ -32,6 +35,7 @@ * @see Files#walkFileTree */ +@AnnotatedFor({"nullness"}) public class FileSystemLoopException extends FileSystemException { @@ -45,7 +49,7 @@ public class FileSystemLoopException * a string identifying the file causing the cycle or {@code null} if * not known */ - public FileSystemLoopException(String file) { + public FileSystemLoopException(@Nullable String file) { super(file); } } diff --git a/src/java.base/share/classes/java/nio/file/FileSystemNotFoundException.java b/src/java.base/share/classes/java/nio/file/FileSystemNotFoundException.java index 0b170fba9a7..c26f478007e 100644 --- a/src/java.base/share/classes/java/nio/file/FileSystemNotFoundException.java +++ b/src/java.base/share/classes/java/nio/file/FileSystemNotFoundException.java @@ -25,12 +25,16 @@ package java.nio.file; + +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; /** * Runtime exception thrown when a file system cannot be found. * * @since 1.7 */ +@AnnotatedFor({"nullness"}) public class FileSystemNotFoundException extends RuntimeException { @@ -49,7 +53,7 @@ public FileSystemNotFoundException() { * @param msg * the detail message */ - public FileSystemNotFoundException(String msg) { + public FileSystemNotFoundException(@Nullable String msg) { super(msg); } } diff --git a/src/java.base/share/classes/java/nio/file/InvalidPathException.java b/src/java.base/share/classes/java/nio/file/InvalidPathException.java index bb28b61b83b..83f77419327 100644 --- a/src/java.base/share/classes/java/nio/file/InvalidPathException.java +++ b/src/java.base/share/classes/java/nio/file/InvalidPathException.java @@ -25,6 +25,8 @@ package java.nio.file; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Unchecked exception thrown when path string cannot be converted into a * {@link Path} because the path string contains invalid characters, or @@ -33,6 +35,7 @@ * @since 1.7 */ +@AnnotatedFor({"nullness"}) public class InvalidPathException extends IllegalArgumentException { diff --git a/src/java.base/share/classes/java/nio/file/NoSuchFileException.java b/src/java.base/share/classes/java/nio/file/NoSuchFileException.java index 73c37e60d57..56858158e39 100644 --- a/src/java.base/share/classes/java/nio/file/NoSuchFileException.java +++ b/src/java.base/share/classes/java/nio/file/NoSuchFileException.java @@ -25,6 +25,9 @@ package java.nio.file; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Checked exception thrown when an attempt is made to access a file that does * not exist. @@ -32,6 +35,7 @@ * @since 1.7 */ +@AnnotatedFor({"nullness"}) public class NoSuchFileException extends FileSystemException { @@ -44,7 +48,7 @@ public class NoSuchFileException * @param file * a string identifying the file or {@code null} if not known. */ - public NoSuchFileException(String file) { + public NoSuchFileException(@Nullable String file) { super(file); } @@ -58,7 +62,7 @@ public NoSuchFileException(String file) { * @param reason * a reason message with additional information or {@code null} */ - public NoSuchFileException(String file, String other, String reason) { + public NoSuchFileException(@Nullable String file, @Nullable String other, @Nullable String reason) { super(file, other, reason); } } diff --git a/src/java.base/share/classes/java/nio/file/NotDirectoryException.java b/src/java.base/share/classes/java/nio/file/NotDirectoryException.java index 225bd2494ff..bad62317c77 100644 --- a/src/java.base/share/classes/java/nio/file/NotDirectoryException.java +++ b/src/java.base/share/classes/java/nio/file/NotDirectoryException.java @@ -25,6 +25,9 @@ package java.nio.file; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Checked exception thrown when a file system operation, intended for a * directory, fails because the file is not a directory. @@ -32,6 +35,7 @@ * @since 1.7 */ +@AnnotatedFor({"nullness"}) public class NotDirectoryException extends FileSystemException { @@ -44,7 +48,7 @@ public class NotDirectoryException * @param file * a string identifying the file or {@code null} if not known */ - public NotDirectoryException(String file) { + public NotDirectoryException(@Nullable String file) { super(file); } } diff --git a/src/java.base/share/classes/java/nio/file/NotLinkException.java b/src/java.base/share/classes/java/nio/file/NotLinkException.java index 02563d35a11..cc8eb09aa1d 100644 --- a/src/java.base/share/classes/java/nio/file/NotLinkException.java +++ b/src/java.base/share/classes/java/nio/file/NotLinkException.java @@ -25,6 +25,9 @@ package java.nio.file; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Checked exception thrown when a file system operation fails because a file * is not a symbolic link. @@ -32,6 +35,7 @@ * @since 1.7 */ +@AnnotatedFor({"nullness"}) public class NotLinkException extends FileSystemException { @@ -44,7 +48,7 @@ public class NotLinkException * @param file * a string identifying the file or {@code null} if not known */ - public NotLinkException(String file) { + public NotLinkException(@Nullable String file) { super(file); } @@ -58,7 +62,7 @@ public NotLinkException(String file) { * @param reason * a reason message with additional information or {@code null} */ - public NotLinkException(String file, String other, String reason) { + public NotLinkException(@Nullable String file, @Nullable String other, @Nullable String reason) { super(file, other, reason); } } diff --git a/src/java.base/share/classes/java/nio/file/ProviderMismatchException.java b/src/java.base/share/classes/java/nio/file/ProviderMismatchException.java index 70c1fad64ab..78d9d0cb40b 100644 --- a/src/java.base/share/classes/java/nio/file/ProviderMismatchException.java +++ b/src/java.base/share/classes/java/nio/file/ProviderMismatchException.java @@ -25,6 +25,9 @@ package java.nio.file; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Unchecked exception thrown when an attempt is made to invoke a method on an * object created by one file system provider with a parameter created by a @@ -32,6 +35,7 @@ * * @since 1.7 */ +@AnnotatedFor({"nullness"}) public class ProviderMismatchException extends java.lang.IllegalArgumentException { @@ -50,7 +54,7 @@ public ProviderMismatchException() { * @param msg * the detail message */ - public ProviderMismatchException(String msg) { + public ProviderMismatchException(@Nullable String msg) { super(msg); } } diff --git a/src/java.base/share/classes/java/nio/file/ProviderNotFoundException.java b/src/java.base/share/classes/java/nio/file/ProviderNotFoundException.java index 804f4996de2..192eae1f802 100644 --- a/src/java.base/share/classes/java/nio/file/ProviderNotFoundException.java +++ b/src/java.base/share/classes/java/nio/file/ProviderNotFoundException.java @@ -25,12 +25,16 @@ package java.nio.file; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Runtime exception thrown when a provider of the required type cannot be found. * * @since 1.7 */ +@AnnotatedFor({"nullness"}) public class ProviderNotFoundException extends RuntimeException { @@ -49,7 +53,7 @@ public ProviderNotFoundException() { * @param msg * the detail message */ - public ProviderNotFoundException(String msg) { + public ProviderNotFoundException(@Nullable String msg) { super(msg); } } diff --git a/src/java.base/share/classes/java/nio/file/ReadOnlyFileSystemException.java b/src/java.base/share/classes/java/nio/file/ReadOnlyFileSystemException.java index d187ef96b68..4284144164f 100644 --- a/src/java.base/share/classes/java/nio/file/ReadOnlyFileSystemException.java +++ b/src/java.base/share/classes/java/nio/file/ReadOnlyFileSystemException.java @@ -25,6 +25,8 @@ package java.nio.file; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Unchecked exception thrown when an attempt is made to update an object * associated with a {@link FileSystem#isReadOnly() read-only} {@code FileSystem}. @@ -32,6 +34,7 @@ * @since 1.7 */ +@AnnotatedFor({"nullness"}) public class ReadOnlyFileSystemException extends UnsupportedOperationException { diff --git a/src/java.base/share/classes/java/util/concurrent/BrokenBarrierException.java b/src/java.base/share/classes/java/util/concurrent/BrokenBarrierException.java index 11f126e015a..fb1e2fa1a97 100644 --- a/src/java.base/share/classes/java/util/concurrent/BrokenBarrierException.java +++ b/src/java.base/share/classes/java/util/concurrent/BrokenBarrierException.java @@ -35,6 +35,9 @@ package java.util.concurrent; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Exception thrown when a thread tries to wait upon a barrier that is * in a broken state, or which enters the broken state while the thread @@ -45,6 +48,7 @@ * @since 1.5 * @author Doug Lea */ +@AnnotatedFor({"nullness"}) public class BrokenBarrierException extends Exception { private static final long serialVersionUID = 7117394618823254244L; @@ -60,7 +64,7 @@ public BrokenBarrierException() {} * * @param message the detail message */ - public BrokenBarrierException(String message) { + public BrokenBarrierException(@Nullable String message) { super(message); } } diff --git a/src/java.base/share/classes/java/util/concurrent/CompletionException.java b/src/java.base/share/classes/java/util/concurrent/CompletionException.java index 2a3cfc56adf..8a076475815 100644 --- a/src/java.base/share/classes/java/util/concurrent/CompletionException.java +++ b/src/java.base/share/classes/java/util/concurrent/CompletionException.java @@ -35,6 +35,9 @@ package java.util.concurrent; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Exception thrown when an error or other exception is encountered * in the course of completing a result or task. @@ -42,6 +45,7 @@ * @since 1.8 * @author Doug Lea */ +@AnnotatedFor({"nullness"}) public class CompletionException extends RuntimeException { private static final long serialVersionUID = 7830266012832686185L; @@ -59,7 +63,7 @@ protected CompletionException() { } * * @param message the detail message */ - protected CompletionException(String message) { + protected CompletionException(@Nullable String message) { super(message); } @@ -71,7 +75,7 @@ protected CompletionException(String message) { * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method) */ - public CompletionException(String message, Throwable cause) { + public CompletionException(@Nullable String message, @Nullable Throwable cause) { super(message, cause); } @@ -84,7 +88,7 @@ public CompletionException(String message, Throwable cause) { * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method) */ - public CompletionException(Throwable cause) { + public CompletionException(@Nullable Throwable cause) { super(cause); } } diff --git a/src/java.base/share/classes/java/util/concurrent/RejectedExecutionException.java b/src/java.base/share/classes/java/util/concurrent/RejectedExecutionException.java index 87feef49513..8529b89af11 100644 --- a/src/java.base/share/classes/java/util/concurrent/RejectedExecutionException.java +++ b/src/java.base/share/classes/java/util/concurrent/RejectedExecutionException.java @@ -35,6 +35,9 @@ package java.util.concurrent; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Exception thrown by an {@link Executor} when a task cannot be * accepted for execution. @@ -42,6 +45,7 @@ * @since 1.5 * @author Doug Lea */ +@AnnotatedFor({"nullness"}) public class RejectedExecutionException extends RuntimeException { private static final long serialVersionUID = -375805702767069545L; @@ -60,7 +64,7 @@ public RejectedExecutionException() { } * * @param message the detail message */ - public RejectedExecutionException(String message) { + public RejectedExecutionException(@Nullable String message) { super(message); } @@ -72,7 +76,7 @@ public RejectedExecutionException(String message) { * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method) */ - public RejectedExecutionException(String message, Throwable cause) { + public RejectedExecutionException(@Nullable String message, @Nullable Throwable cause) { super(message, cause); } @@ -85,7 +89,7 @@ public RejectedExecutionException(String message, Throwable cause) { * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method) */ - public RejectedExecutionException(Throwable cause) { + public RejectedExecutionException(@Nullable Throwable cause) { super(cause); } } From b96c075d6b118998fd75ba4efe4767cad1332f59 Mon Sep 17 00:00:00 2001 From: Suzanne Millstein Date: Fri, 21 Nov 2025 09:07:22 -0800 Subject: [PATCH 30/82] Added null annotations based on javadoc for the public nio classes (#245) Co-authored-by: Davy Landman Co-authored-by: Davy Landman --- .../classes/java/nio/file/FileStore.java | 7 ++++--- .../classes/java/nio/file/FileSystems.java | 9 +++++---- .../classes/java/nio/file/FileVisitor.java | 6 +++++- .../share/classes/java/nio/file/Files.java | 19 ++++++++++--------- .../classes/java/nio/file/LinkPermission.java | 7 ++++++- .../java/nio/file/SecureDirectoryStream.java | 9 +++++++-- .../java/nio/file/SimpleFileVisitor.java | 5 +++-- .../classes/java/nio/file/WatchEvent.java | 8 ++++++-- .../classes/java/nio/file/WatchService.java | 7 ++++--- .../attribute/BasicFileAttributeView.java | 10 +++++++--- .../file/attribute/BasicFileAttributes.java | 5 +++-- .../java/nio/file/spi/FileSystemProvider.java | 7 ++++--- .../java/nio/file/spi/FileTypeDetector.java | 5 +++-- 13 files changed, 67 insertions(+), 37 deletions(-) diff --git a/src/java.base/share/classes/java/nio/file/FileStore.java b/src/java.base/share/classes/java/nio/file/FileStore.java index 88c309b4370..18f6aa7982f 100644 --- a/src/java.base/share/classes/java/nio/file/FileStore.java +++ b/src/java.base/share/classes/java/nio/file/FileStore.java @@ -27,6 +27,7 @@ import org.checkerframework.checker.interning.qual.UsesObjectEquals; import org.checkerframework.framework.qual.AnnotatedFor; +import org.checkerframework.checker.nullness.qual.Nullable; import java.nio.file.attribute.*; import java.io.IOException; @@ -46,7 +47,7 @@ * @since 1.7 */ -@AnnotatedFor({"interning"}) +@AnnotatedFor({"interning", "nullness"}) public abstract @UsesObjectEquals class FileStore { /** @@ -215,7 +216,7 @@ public long getBlockSize() throws IOException { * @return a file store attribute view of the specified type or * {@code null} if the attribute view is not available */ - public abstract V + public abstract V getFileStoreAttributeView(Class type); /** @@ -251,5 +252,5 @@ public long getBlockSize() throws IOException { * @throws IOException * if an I/O error occurs */ - public abstract Object getAttribute(String attribute) throws IOException; + public abstract @Nullable Object getAttribute(String attribute) throws IOException; } diff --git a/src/java.base/share/classes/java/nio/file/FileSystems.java b/src/java.base/share/classes/java/nio/file/FileSystems.java index 49c3710cc02..a5c86d3ffb6 100644 --- a/src/java.base/share/classes/java/nio/file/FileSystems.java +++ b/src/java.base/share/classes/java/nio/file/FileSystems.java @@ -27,6 +27,7 @@ import org.checkerframework.checker.interning.qual.UsesObjectEquals; import org.checkerframework.framework.qual.AnnotatedFor; +import org.checkerframework.checker.nullness.qual.Nullable; import java.nio.file.spi.FileSystemProvider; import java.net.URI; @@ -89,7 +90,7 @@ * @since 1.7 */ -@AnnotatedFor({"interning"}) +@AnnotatedFor({"interning", "nullness"}) public final @UsesObjectEquals class FileSystems { private FileSystems() { } @@ -331,7 +332,7 @@ public static FileSystem newFileSystem(URI uri, Map env) * if a security manager is installed and it denies an unspecified * permission required by the file system provider implementation */ - public static FileSystem newFileSystem(URI uri, Map env, ClassLoader loader) + public static FileSystem newFileSystem(URI uri, Map env, @Nullable ClassLoader loader) throws IOException { String scheme = uri.getScheme(); @@ -398,7 +399,7 @@ public static FileSystem newFileSystem(URI uri, Map env, ClassLoader l * permission */ public static FileSystem newFileSystem(Path path, - ClassLoader loader) + @Nullable ClassLoader loader) throws IOException { return newFileSystem(path, Map.of(), loader); @@ -521,7 +522,7 @@ public static FileSystem newFileSystem(Path path) throws IOException { * @since 13 */ public static FileSystem newFileSystem(Path path, Map env, - ClassLoader loader) + @Nullable ClassLoader loader) throws IOException { if (path == null) diff --git a/src/java.base/share/classes/java/nio/file/FileVisitor.java b/src/java.base/share/classes/java/nio/file/FileVisitor.java index 5c555ae77e1..fe0816059ef 100644 --- a/src/java.base/share/classes/java/nio/file/FileVisitor.java +++ b/src/java.base/share/classes/java/nio/file/FileVisitor.java @@ -28,6 +28,9 @@ import java.nio.file.attribute.BasicFileAttributes; import java.io.IOException; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * A visitor of files. An implementation of this interface is provided to the * {@link Files#walkFileTree Files.walkFileTree} methods to visit each file in @@ -95,6 +98,7 @@ * @since 1.7 */ +@AnnotatedFor({"nullness"}) public interface FileVisitor { /** @@ -172,6 +176,6 @@ FileVisitResult visitFileFailed(T file, IOException exc) * @throws IOException * if an I/O error occurs */ - FileVisitResult postVisitDirectory(T dir, IOException exc) + FileVisitResult postVisitDirectory(T dir, @Nullable IOException exc) throws IOException; } diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java index 2cb920d6d44..0a79e512a24 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -35,6 +35,7 @@ import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.dataflow.qual.SideEffectsOnly; import org.checkerframework.framework.qual.AnnotatedFor; +import org.checkerframework.checker.nullness.qual.Nullable; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -103,7 +104,7 @@ * @since 1.7 */ -@AnnotatedFor({"interning", "mustcall", "signedness"}) +@AnnotatedFor({"interning", "mustcall", "signedness", "nullness"}) public final @UsesObjectEquals class Files { // buffer size used for reading and writing private static final int BUFFER_SIZE = 8192; @@ -895,8 +896,8 @@ private static void createAndCheckIsDirectory(Path dir, */ @ReleasesNoLocks public static Path createTempFile(Path dir, - String prefix, - String suffix, + @Nullable String prefix, + @Nullable String suffix, FileAttribute... attrs) throws IOException { @@ -941,8 +942,8 @@ public static Path createTempFile(Path dir, * method is invoked to check write access to the file. */ @ReleasesNoLocks - public static Path createTempFile(String prefix, - String suffix, + public static Path createTempFile(@Nullable String prefix, + @Nullable String suffix, FileAttribute... attrs) throws IOException { @@ -996,7 +997,7 @@ public static Path createTempFile(String prefix, */ @ReleasesNoLocks public static Path createTempDirectory(Path dir, - String prefix, + @Nullable String prefix, FileAttribute... attrs) throws IOException { @@ -1038,7 +1039,7 @@ public static Path createTempDirectory(Path dir, * directory. */ @ReleasesNoLocks - public static Path createTempDirectory(String prefix, + public static Path createTempDirectory(@Nullable String prefix, FileAttribute... attrs) throws IOException { @@ -1763,7 +1764,7 @@ private static List loadInstalledDetectors() { * permission required by a file type detector implementation. */ @ReleasesNoLocks - public static String probeContentType(Path path) + public static @Nullable String probeContentType(Path path) throws IOException { // try installed file type detectors @@ -1822,7 +1823,7 @@ public static String probeContentType(Path path) * the attribute view type is not available */ @ReleasesNoLocks - public static V getFileAttributeView(Path path, + public static V getFileAttributeView(Path path, Class type, LinkOption... options) { diff --git a/src/java.base/share/classes/java/nio/file/LinkPermission.java b/src/java.base/share/classes/java/nio/file/LinkPermission.java index 81921f059cb..f102eae2670 100644 --- a/src/java.base/share/classes/java/nio/file/LinkPermission.java +++ b/src/java.base/share/classes/java/nio/file/LinkPermission.java @@ -27,6 +27,9 @@ import java.security.BasicPermission; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * The {@code Permission} class for link creation operations. * @@ -66,6 +69,8 @@ * @see Files#createLink * @see Files#createSymbolicLink */ + +@AnnotatedFor({"nullness"}) public final class LinkPermission extends BasicPermission { @java.io.Serial static final long serialVersionUID = -1441492453772213220L; @@ -102,7 +107,7 @@ public LinkPermission(String name) { * @throws IllegalArgumentException * if name is empty or invalid, or actions is a non-empty string */ - public LinkPermission(String name, String actions) { + public LinkPermission(String name, @Nullable String actions) { super(name); checkName(name); if (actions != null && !actions.isEmpty()) { diff --git a/src/java.base/share/classes/java/nio/file/SecureDirectoryStream.java b/src/java.base/share/classes/java/nio/file/SecureDirectoryStream.java index 8cfaea35f4a..f04d5b47a65 100644 --- a/src/java.base/share/classes/java/nio/file/SecureDirectoryStream.java +++ b/src/java.base/share/classes/java/nio/file/SecureDirectoryStream.java @@ -29,6 +29,9 @@ import java.util.Set; import java.io.IOException; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * A {@code DirectoryStream} that defines operations on files that are located * relative to an open directory. A {@code SecureDirectoryStream} is intended @@ -56,6 +59,8 @@ * @since 1.7 */ +@AnnotatedFor({"nullness"}) + public interface SecureDirectoryStream extends DirectoryStream { @@ -271,7 +276,7 @@ void move(T srcpath, SecureDirectoryStream targetdir, T targetpath) * this directory stream, or {@code null} if the attribute view * type is not available */ - V getFileAttributeView(Class type); + @Nullable V getFileAttributeView(Class type); /** * Returns a new file attribute view to access the file attributes of a file @@ -306,7 +311,7 @@ void move(T srcpath, SecureDirectoryStream targetdir, T targetpath) * type is not available * */ - V getFileAttributeView(T path, + @Nullable V getFileAttributeView(T path, Class type, LinkOption... options); } diff --git a/src/java.base/share/classes/java/nio/file/SimpleFileVisitor.java b/src/java.base/share/classes/java/nio/file/SimpleFileVisitor.java index b4e9713c8e5..d9dacce1270 100644 --- a/src/java.base/share/classes/java/nio/file/SimpleFileVisitor.java +++ b/src/java.base/share/classes/java/nio/file/SimpleFileVisitor.java @@ -26,6 +26,7 @@ package java.nio.file; import org.checkerframework.checker.interning.qual.UsesObjectEquals; +import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.framework.qual.AnnotatedFor; import java.nio.file.attribute.BasicFileAttributes; @@ -43,7 +44,7 @@ * @since 1.7 */ -@AnnotatedFor({"interning"}) +@AnnotatedFor({"interning", "nullness"}) public @UsesObjectEquals class SimpleFileVisitor implements FileVisitor { /** * Initializes a new instance of this class. @@ -105,7 +106,7 @@ public FileVisitResult visitFileFailed(T file, IOException exc) * of the directory to terminate prematurely. */ @Override - public FileVisitResult postVisitDirectory(T dir, IOException exc) + public FileVisitResult postVisitDirectory(T dir, @Nullable IOException exc) throws IOException { Objects.requireNonNull(dir); diff --git a/src/java.base/share/classes/java/nio/file/WatchEvent.java b/src/java.base/share/classes/java/nio/file/WatchEvent.java index 25438a86f9a..e71fc710d88 100644 --- a/src/java.base/share/classes/java/nio/file/WatchEvent.java +++ b/src/java.base/share/classes/java/nio/file/WatchEvent.java @@ -25,6 +25,9 @@ package java.nio.file; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * An event or a repeated event for an object that is registered with a {@link * WatchService}. @@ -44,7 +47,8 @@ * @since 1.7 */ -public interface WatchEvent { +@AnnotatedFor({"nullness"}) +public interface WatchEvent { /** * An event kind, for the purposes of identification. @@ -52,7 +56,7 @@ public interface WatchEvent { * @since 1.7 * @see StandardWatchEventKinds */ - public static interface Kind { + public static interface Kind { /** * Returns the name of the event kind. * diff --git a/src/java.base/share/classes/java/nio/file/WatchService.java b/src/java.base/share/classes/java/nio/file/WatchService.java index 042df2458f0..2b5961571ee 100644 --- a/src/java.base/share/classes/java/nio/file/WatchService.java +++ b/src/java.base/share/classes/java/nio/file/WatchService.java @@ -31,6 +31,7 @@ import org.checkerframework.checker.mustcall.qual.InheritableMustCall; import org.checkerframework.framework.qual.AnnotatedFor; +import org.checkerframework.checker.nullness.qual.Nullable; /** * A watch service that watches registered objects for changes and @@ -105,7 +106,7 @@ * * @see FileSystem#newWatchService */ -@AnnotatedFor({"mustcall"}) +@AnnotatedFor({"mustcall", "nullness"}) @InheritableMustCall({}) public interface WatchService extends Closeable @@ -140,7 +141,7 @@ public interface WatchService * @throws ClosedWatchServiceException * if this watch service is closed */ - WatchKey poll(); + @Nullable WatchKey poll(); /** * Retrieves and removes the next watch key, waiting if necessary up to the @@ -160,7 +161,7 @@ public interface WatchService * @throws InterruptedException * if interrupted while waiting */ - WatchKey poll(long timeout, TimeUnit unit) + @Nullable WatchKey poll(long timeout, TimeUnit unit) throws InterruptedException; /** diff --git a/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributeView.java b/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributeView.java index 37508cfd200..0678814797a 100644 --- a/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributeView.java +++ b/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributeView.java @@ -27,6 +27,9 @@ import java.io.IOException; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * A file attribute view that provides a view of a basic set of file * attributes common to many file systems. The basic set of file attributes @@ -101,6 +104,7 @@ * @since 1.7 */ +@AnnotatedFor({"nullness"}) public interface BasicFileAttributeView extends FileAttributeView { @@ -176,7 +180,7 @@ public interface BasicFileAttributeView * * @see java.nio.file.Files#setLastModifiedTime */ - void setTimes(FileTime lastModifiedTime, - FileTime lastAccessTime, - FileTime createTime) throws IOException; + void setTimes(@Nullable FileTime lastModifiedTime, + @Nullable FileTime lastAccessTime, + @Nullable FileTime createTime) throws IOException; } diff --git a/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributes.java b/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributes.java index 2c20c09df88..712fe7c31f4 100644 --- a/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributes.java +++ b/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributes.java @@ -27,6 +27,7 @@ import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.framework.qual.AnnotatedFor; +import org.checkerframework.checker.nullness.qual.Nullable; /** * Basic attributes associated with a file in a file system. @@ -46,7 +47,7 @@ * @see BasicFileAttributeView */ -@AnnotatedFor({"index"}) +@AnnotatedFor({"index", "nullness"}) public interface BasicFileAttributes { /** @@ -155,5 +156,5 @@ public interface BasicFileAttributes { * * @see java.nio.file.Files#walkFileTree */ - Object fileKey(); + @Nullable Object fileKey(); } diff --git a/src/java.base/share/classes/java/nio/file/spi/FileSystemProvider.java b/src/java.base/share/classes/java/nio/file/spi/FileSystemProvider.java index 5f1741f1f37..90ec81611ad 100644 --- a/src/java.base/share/classes/java/nio/file/spi/FileSystemProvider.java +++ b/src/java.base/share/classes/java/nio/file/spi/FileSystemProvider.java @@ -26,6 +26,7 @@ package java.nio.file.spi; import org.checkerframework.checker.interning.qual.UsesObjectEquals; +import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.framework.qual.AnnotatedFor; import java.nio.channels.AsynchronousFileChannel; @@ -113,7 +114,7 @@ * @since 1.7 */ -@AnnotatedFor({"interning"}) +@AnnotatedFor({"interning", "nullness"}) public abstract @UsesObjectEquals class FileSystemProvider { // lock using when loading providers private static final Object lock = new Object(); @@ -586,7 +587,7 @@ public FileChannel newFileChannel(Path path, */ public AsynchronousFileChannel newAsynchronousFileChannel(Path path, Set options, - ExecutorService executor, + @Nullable ExecutorService executor, FileAttribute... attrs) throws IOException { @@ -1074,7 +1075,7 @@ public abstract void checkAccess(Path path, AccessMode... modes) * @return a file attribute view of the specified type, or {@code null} if * the attribute view type is not available */ - public abstract V + public abstract V getFileAttributeView(Path path, Class type, LinkOption... options); /** diff --git a/src/java.base/share/classes/java/nio/file/spi/FileTypeDetector.java b/src/java.base/share/classes/java/nio/file/spi/FileTypeDetector.java index 5c64c267ec1..29dac692d49 100644 --- a/src/java.base/share/classes/java/nio/file/spi/FileTypeDetector.java +++ b/src/java.base/share/classes/java/nio/file/spi/FileTypeDetector.java @@ -25,6 +25,7 @@ package java.nio.file.spi; +import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.interning.qual.UsesObjectEquals; import org.checkerframework.framework.qual.AnnotatedFor; @@ -50,7 +51,7 @@ * @since 1.7 */ -@AnnotatedFor({"interning"}) +@AnnotatedFor({"interning", "nullable"}) public abstract @UsesObjectEquals class FileTypeDetector { private static Void checkPermission() { @@ -106,6 +107,6 @@ protected FileTypeDetector() { * * @see java.nio.file.Files#probeContentType */ - public abstract String probeContentType(Path path) + public abstract @Nullable String probeContentType(Path path) throws IOException; } From ecc60338caa93c8713d4ae35ae8c858b23ce4f1f Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Wed, 26 Nov 2025 21:43:13 -0800 Subject: [PATCH 31/82] Write `@Identifier` on `Method.getName()` --- src/java.base/share/classes/java/lang/reflect/Method.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/lang/reflect/Method.java b/src/java.base/share/classes/java/lang/reflect/Method.java index a1d7fbd653a..652f513ba0d 100644 --- a/src/java.base/share/classes/java/lang/reflect/Method.java +++ b/src/java.base/share/classes/java/lang/reflect/Method.java @@ -28,6 +28,7 @@ import org.checkerframework.checker.interning.qual.Interned; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.checker.signature.qual.Identifier; import org.checkerframework.common.reflection.qual.Invoke; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; @@ -239,7 +240,7 @@ public Class getDeclaringClass() { * object, as a {@code String}. */ @Override - public @Interned String getName() { + public @Interned @Identifier String getName() { return name; } From 4ce078798c480438bdfe48b7a22b43c2fa22e6cd Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 28 Nov 2025 16:39:50 -0800 Subject: [PATCH 32/82] Add `@Identifier` in `StackTraceElement` --- .../share/classes/java/lang/StackTraceElement.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/lang/StackTraceElement.java b/src/java.base/share/classes/java/lang/StackTraceElement.java index 27b5bd237a2..37700f4e172 100644 --- a/src/java.base/share/classes/java/lang/StackTraceElement.java +++ b/src/java.base/share/classes/java/lang/StackTraceElement.java @@ -28,6 +28,7 @@ import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.signature.qual.FullyQualifiedName; +import org.checkerframework.checker.signature.qual.Identifier; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -124,7 +125,7 @@ public final class StackTraceElement implements java.io.Serializable { * @since 1.5 * @revised 9 */ - public StackTraceElement(@FullyQualifiedName String declaringClass, String methodName, + public StackTraceElement(@FullyQualifiedName String declaringClass, @Identifier String methodName, @Nullable String fileName, int lineNumber) { this(null, null, null, declaringClass, methodName, fileName, lineNumber); } @@ -162,7 +163,7 @@ public StackTraceElement(@FullyQualifiedName String declaringClass, String metho */ public StackTraceElement(String classLoaderName, String moduleName, String moduleVersion, - String declaringClass, String methodName, + String declaringClass, @Identifier String methodName, String fileName, int lineNumber) { this.classLoaderName = classLoaderName; this.moduleName = moduleName; @@ -275,7 +276,7 @@ public String getClassLoaderName() { * @return the name of the method containing the execution point * represented by this stack trace element. */ - public String getMethodName(@GuardSatisfied StackTraceElement this) { + public @Identifier String getMethodName(@GuardSatisfied StackTraceElement this) { return methodName; } From 985c44f37ad7c6239841a5f9188888840dc70339 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Mon, 1 Dec 2025 12:12:40 -0800 Subject: [PATCH 33/82] More signature annotations --- src/java.base/share/classes/java/lang/constant/ClassDesc.java | 4 +++- .../share/classes/java/lang/constant/MethodTypeDesc.java | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/lang/constant/ClassDesc.java b/src/java.base/share/classes/java/lang/constant/ClassDesc.java index 435d992fa50..2178151f1ce 100644 --- a/src/java.base/share/classes/java/lang/constant/ClassDesc.java +++ b/src/java.base/share/classes/java/lang/constant/ClassDesc.java @@ -24,6 +24,8 @@ */ package java.lang.constant; +import org.checkerframework.checker.signature.qual.FieldDescriptor; + import java.lang.invoke.TypeDescriptor; import java.util.stream.Stream; @@ -316,7 +318,7 @@ else if (isArray()) { * @return the descriptor string * @jvms 4.3.2 Field Descriptors */ - String descriptorString(); + @FieldDescriptor String descriptorString(); /** * Compare the specified object with this descriptor for equality. Returns diff --git a/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java b/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java index 4750231ce37..48216343184 100644 --- a/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java +++ b/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java @@ -24,6 +24,8 @@ */ package java.lang.constant; +import org.checkerframework.checker.signature.qual.MethodDescriptor; + import java.lang.invoke.MethodType; import java.lang.invoke.TypeDescriptor; import java.util.List; @@ -166,7 +168,7 @@ static MethodTypeDesc of(ClassDesc returnDesc, ClassDesc... paramDescs) { * @return the method type descriptor string * @jvms 4.3.3 Method Descriptors */ - default String descriptorString() { + default @MethodDescriptor String descriptorString() { return String.format("(%s)%s", Stream.of(parameterArray()) .map(ClassDesc::descriptorString) From 0fcac1fb4f7465f4141f098e7288fcf7e581e4a8 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 16 Dec 2025 04:49:20 -0800 Subject: [PATCH 34/82] Improve Markdown style --- README.md | 66 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index ce91a26266c..1a899ff44b0 100644 --- a/README.md +++ b/README.md @@ -5,15 +5,15 @@ It is called "the annotated JDK". It does *not* contain annotations for certain files (because annotations in them cause build failures, especially in the interim builds): - * the jdk.rmic module - * objectweb/asm files - * src/java.base/share/classes/java/time/* - * src/jdk.compiler/share/classes/com/sun/tools/javac/* + +* the jdk.rmic module +* objectweb/asm files +* src/java.base/share/classes/java/time/* +* src/jdk.compiler/share/classes/com/sun/tools/javac/* Annotations for classes that exist in JDK version X but were removed later appear in jdkX.astub files, such as jdk11.astub, in repository -https://github.com/typetools/checker-framework/ . - + . ## Building @@ -31,18 +31,18 @@ However, if for some reason you want to build the JDK on its own rather than just use it from the Checker Framework, see file `azure-pipelines.yml`. Briefly: -``` +```sh bash configure --disable-warnings-as-errors --with-jtreg make jdk ``` You might need to change `--with-jtreg` to one of these: -``` + +```sh --with-jtreg=/usr/share/jtreg --with-jtreg=$HOME/bin/install/jtreg ``` - ## Contributing We welcome pull requests that add new annotations or correct existing ones. @@ -50,8 +50,7 @@ Thanks in advance for your contributions! When adding annotations, please annotate an entire file at a time, and add an `@AnnotatedFor` annotation on the class declaration. The rationale is explained -at https://checkerframework.org/manual/#library-tips-fully-annotate . - +at . ## Relationship to other repositories @@ -59,7 +58,7 @@ The typetools:jdk fork is not up to date with respect to `openjdk:jdk` (the current OpenJDK version). The typetools:jdk fork contains all commits through the release of JDK 20 (that is, the last commit that is in both openjdk:jdk and in openjdk:jdk20u): -https://github.com/typetools/jdk/commit/d562d3fcbe22a0443037c5b447e1a41401275814 + The typetools:jdk fork is an ancestor of JDK release forks such as typetools:jdk17u. The typetools:jdk fork may not compile, because the commit of @@ -71,7 +70,6 @@ This fork's annotations are pulled into those repositories, in order to build an annotated JDK. We do not write annotations in (say) typetools:jdk20u, because it would be painful to get them into typetools:jdk21u due to subsequent commits. - ## Pull request merge conflicts If a pull request is failing with a merge conflict in `jdk17u`, first @@ -81,7 +79,9 @@ update jdk17u from its upstreams, using the directions in section If that does not resolve the issue, then do the following in a clone of the branch of `jdk` whose pull request is failing. -``` + + +```sh BRANCH=`git rev-parse --abbrev-ref HEAD` URL=`git config --get remote.origin.url` SLUG=${URL#*:} @@ -103,24 +103,23 @@ git pull $URL $BRANCH Manual step: resolve conflicts and complete the merge. -``` +```sh git push --set-upstream origin $BRANCH ``` Manual step: restart the pull request CI job. -After the pull request is merged to https://github.com/typetools/jdk, -follow the instructions at https://github.com/typetools/jdk17u to update +After the pull request is merged to , +follow the instructions at to update jdk17u, taking guidance from the merge done in the fork of jdk17u to resolve conflicts. Then, discard the branch in the fork of jdk17u. - ## Qualifier definitions The java.base module contains a copy of the Checker Framework qualifiers (type annotations). To update that copy, run the command below from this directory: -``` +```sh (cd $CHECKERFRAMEWORK && rm -rf checker-qual/build/libs && ./gradlew :checker-qual:sourcesJar) && \ rm -f checker-qual.jar && \ cp -p $CHECKERFRAMEWORK/checker-qual/build/libs/checker-qual-*-sources.jar checker-qual.jar && \ @@ -130,6 +129,7 @@ cp -p $CHECKERFRAMEWORK/checker-qual/build/libs/checker-qual-*-sources.jar check chmod -R u+w org/checkerframework) && \ jar tf checker-qual.jar | grep '\.java$' | sed 's/\/[^/]*\.java/;/' | sed 's/\//./g' | sed 's/^/ exports /' | sort -u ``` + The result of the command will be a list of export lines. Replace the existing export lines present in `src/java.base/share/classes/module-info.java` with the newly-generated list of @@ -139,7 +139,6 @@ in the `module-info.java` file. Commit the changes, including the new `checker.jar` file and any new `.java` files in a `qual/` directory. (Both are used, by different parts of the build.) - ## The typetools/jdk17u repository The typetools/jdk17u repository is a merge of `openjdk/jdk17u` and `typetools/jdk`. @@ -147,30 +146,34 @@ That is, it is a fork of `openjdk/jdk17u`, with Checker Framework type annotatio **Do not edit the `typetools/jdk17u` repository.** Make changes in the `typetools/jdk` repository. -(Note that this README file appears in both the `typetools/jdk` and `typetools/jdk17u` repositories!) +(Note that this README file appears in both the `typetools/jdk` +and `typetools/jdk17u` repositories!) To update jdk17u from its upstreams: -(These are the only edits to jdk17u allowed, plus changes needed to resolve merge conflicts.) -``` +(These are the only edits to jdk17u allowed, plus changes needed to resolve +merge conflicts.) + +```sh cd jdk17u git pull git pull https://github.com/openjdk/jdk17u.git git pull https://github.com/typetools/jdk.git ``` - ## Updating -Whenever a new Java release is made, this repository should be updated to pull in more commits from upstream. Here are some commands to run when updating to JDK ${VER}. +Whenever Oracle relasese a new version of Java, this repository should be +updated to pull in more commits from upstream. Here are some commands to run +when updating to JDK ${VER}. -Fork into typetools: https://github.com/openjdk/jdk${VER}u +Fork into typetools: Clone jdk${VER}u repositories into, say, $t/libraries/ . Determine the last commit in both openjdk:jdk and in openjdk:jdk${VER}u: run `git log --graph | tac` on both and find the common prefix. -``` +```sh last_common_commit=d562d3fcbe22a0443037c5b447e1a41401275814 cd $t/libraries git clone -- git@github.com:openjdk/jdk.git jdk-fork-openjdk-commit-${last_common_commit} @@ -181,7 +184,6 @@ cd $t/libraries/jdk-fork-${USER}-branch-jdk${VER} git pull ../jdk-fork-openjdk-commit-${last_common_commit} ``` - ## Design The goal of this repository is to write Checker Framework annotations in @@ -190,20 +192,20 @@ those annotations are available -- in a module such as java.base, or on the classpath. I tried putting them in `java.base` (which worked for JDK 11), but I wasn't able to make that work for JDK 17. - ## Upstream README follows The remainder of this file is the `README.md` from `openjdk/jdk`. + -# Welcome to the JDK! +# Welcome to the JDK For build instructions please see the [online documentation](https://openjdk.java.net/groups/build/doc/building.html), or either of these files: -- [doc/building.html](doc/building.html) (html version) -- [doc/building.md](doc/building.md) (markdown version) +* [doc/building.html](doc/building.html) (html version) +* [doc/building.md](doc/building.md) (markdown version) See for more information about the OpenJDK Community and the JDK. From f03a7797abb0e62b8855cec045f388c09794e62f Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Wed, 17 Dec 2025 10:18:17 -0800 Subject: [PATCH 35/82] Don't run CI job that fails --- .github/workflows/{main.yml => main.yml-orig} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{main.yml => main.yml-orig} (100%) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml-orig similarity index 100% rename from .github/workflows/main.yml rename to .github/workflows/main.yml-orig From 865d19a2c46e894b675497f7149b8de189e1fc9d Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Wed, 17 Dec 2025 10:18:33 -0800 Subject: [PATCH 36/82] Don't squash-and-merge during version upgrade --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 29ac0b3a630..9cfb35639ad 100644 --- a/README.md +++ b/README.md @@ -219,6 +219,9 @@ git pull ../jdk-fork-${USER}-branch-jdk21 Push and wait for CI to pass. +DO NOT squash-and-merge the pull request. Both the jdk and jdk21u repositories +need to be merged, retaining history. + ## Design The goal of this repository is to write Checker Framework annotations in From c2c4b0769aa7f5fc56ead6d14e0b3ed2272eebfd Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Wed, 17 Dec 2025 10:19:32 -0800 Subject: [PATCH 37/82] Emacs commands to assist version upgrade --- README-diffing.el | 33 +++++++++++++++ README-merging.el | 105 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 README-diffing.el create mode 100644 README-merging.el diff --git a/README-diffing.el b/README-diffing.el new file mode 100644 index 00000000000..dd5120bc1c6 --- /dev/null +++ b/README-diffing.el @@ -0,0 +1,33 @@ +;; Given a context diff between the Java JDK and the Checker Framework's +;; annotated JDK, run these commands to reduce the size of the diffs. Most +;; remaining diffs indicate an unintentional edit that should be reverted in the +;; annotated JDK. + +(progn + (save-excursion + (goto-char (point-min)) + + (save-excursion + (delete-matching-lines "^\\+import org.checkerframework.*;$" nil nil t)) + + (save-excursion + (replace-string "\n \n+\n" "\n \n")) + + (save-excursion + (delete-matching-lines (concat "^\\+" annotation-line-regex "$"))) + + (save-excursion + (query-replace-regexp "@[A-Z][A-Za-z0-9_]* " "")) + (save-excursion + (query-replace-regexp "@[A-Z][A-Za-z0-9_]*([^()\n]*) " "")) + (save-excursion + (query-replace " []" "[]")) + (save-excursion + (query-replace " ..." "...")) + (save-excursion + (query-replace-regexp " \\([A-Za-z0-9_]*(\\)[A-Z][A-Za-z0-9_.]*\\(<[A-Z]\\(, ?[A-Z]\\)*>\\)? this, " " \\1")) + (save-excursion + (query-replace-regexp " \\([A-Za-z0-9_]*(\\)[A-Z][A-Za-z0-9_.]*\\(<[A-Z]\\(, ?[A-Z]\\)*>\\)? this)" " \\1)")) + (save-excursion + (query-replace-regexp " extends Object\\([,>]\\)" "\\1")) + )) diff --git a/README-merging.el b/README-merging.el new file mode 100644 index 00000000000..03c5eac98df --- /dev/null +++ b/README-merging.el @@ -0,0 +1,105 @@ +;; This file contains editor commands that are helpful when merging the JDK. + +;; Run at the top level: etags $(rg --files-with-matches '<<<<<<') +;; Then, visit that tags table and run these expressions. + +;; To fix Java array declarations from +;; "short a2[]" to "short[] a2" or from +;; "@PolySigned short a2 @Nullable []" to "@PolySigned short @Nullable [] a2": +(tags-query-replace "\\([^@]\\)\\b\\([A-Z][a-z][A-Za-z0-9]+\\|byte\\|short\\|int\\|long\\|float\\|double\\|boolean\\|char\\) \\([A-Za-z0-9]+\\)\\(\\( ?@[A-Za-z0-9]+ ?\\)*\\[\\]\\)" "\\1\\2\\4 \\3") + +(defvar annotation-line-regex) +(setq annotation-line-regex + " *@\\(CallerSensitive\\|ForceInline\\|Override\\|Covariant({[0-9]})\\|CreatesMustCallFor\\|Deterministic\\|EqualsMethod\\|ForName\\|FormatMethod\\|GetConstructor\\|GetClass\\|GetMethod\\|InheritableMustCall(.*)\\|I18nMakeFormat\\|Invoke\\|MayReleaseLocks\\|MustCall(.*)\\|NewInstance\\|NotOwning\\|OptionalCreator\\|OptionalEliminator\\|OptionalPropagator\\|PolyUIEffect\\|PolyUIType\\|Pure\\|ReleasesNoLocks\\|SafeEffect\\|SideEffectFree\\|SideEffectsOnly.*\\|StaticallyExecutable\\|TerminatesExecution\\|UIEffect\\|UIPackage\\|UIType\\|UsesObjectEquals\\|CFComment(.*)\\|Ensures.*\\|Requires.*\\|AnnotatedFor.*\\)") + +;; Move annotations only on the HEAD method before the hunk. +(tags-query-replace + ;; "\\|SuppressWarnings.*" intentionally omitted; it should be the last annotation and should be resolved by hand. + (concat "^\\(<<<<<<< HEAD\n\\)\\(\\(" annotation-line-regex "\n\\)+\\)") + "\\2\\1") + +;; Move annotations only on the OTHER method before the hunk. +(tags-query-replace + (concat "^\\(<<<<<<< HEAD\n[^|]*\n|||||||.*\n[^=]*=======\n\\)\\(\\(?:" annotation-line-regex "\n\\)+\\)") + "\\2\\1") + +;; Move Checker Framework imports before the hunk. +(tags-query-replace + "^\\(<<<<<<< HEAD\n\\)\\(\\(import org.checkerframework..*;\n\\)+\n\\)" + "\\2\\1") + + +;; Resolve the first line of a diff, when HEAD has been edited. +;; This version requires "public" at start of \2 and \4. +(tags-query-replace + (concat + "^\\(<<<<<<< HEAD\n\\)" + "\\( *public .*\n\\)" + "\\(\\(?:\\(?:[^|\n][^\n]*\\)?\n\\)*|||||||.*\n\\)" + "\\( *public .*\n\\)" + "\\(\\(?:\\(?:[^=\n][^\n]*\\)?\n\\)*=======\n\\)" + "\\4") + "\\2\\1\\3\\5") +;; The more general version, which I don't seem to need. +(tags-query-replace + (concat + "^\\(<<<<<<< HEAD\n\\)" + "\\(.*\n\\)" + "\\([^|]*\n|||||||.*\n\\)" + "\\(.*\n\\)" + "\\([^=]*\n=======\n\\)" + "\\4") + "\\2\\1\\3\\5") + +;; Resolve the first line of a diff, when OTHER has been edited. +;; This version requires "public" at start of \2 and \4. +(tags-query-replace + (concat + "^\\(<<<<<<< HEAD\n\\)" + "\\( *public .*\n\\)" + "\\(\\(?:\\(?:[^|\n][^\n]*\\)?\n\\)*|||||||.*\n\\)" + "\\2" + "\\(\\(?:\\(?:[^=\n][^\n]*\\)?\n\\)*=======\n\\)" + "\\( *public .*\n\\)") + "\\5\\1\\3\\4") + +;; Special case for the `equals()` method. +(tags-query-replace + (concat + "<<<<<<< HEAD\n" + " public boolean equals(Object obj) {\n" + "||||||| [0-9a-f]\\{11\\}\n" + " public boolean equals(Object obj) {\n" + "=======\n" + " public boolean equals(@Nullable Object obj) {\n" + ">>>>>>> [0-9a-f]\\{40\\}\n") + " public boolean equals(@Nullable Object obj) {\n") + +;; Resolve completely empty diffs. +(tags-query-replace + (concat + "<<<<<<< HEAD\n" + "||||||| [0-9a-f]\\{11\\}\n" + "=======\n" + ">>>>>>> [0-9a-f]\\{40\\}\n") + "") + +;; Resolve diffs where one of the ancestors is empty. +(tags-query-replace + (concat + "<<<<<<< HEAD\n" + "||||||| [0-9a-f]\\{11\\}\n" + "=======\n" + "\\([^~]*?\\)\n" + ">>>>>>> [0-9a-f]\\{40\\}\n") + "\\1") +(tags-query-replace + (concat + "<<<<<<< HEAD\n" + "\\([^~]*?\n\\)" + "||||||| [0-9a-f]\\{11\\}\n" + "\\1" + "=======\n" + "\\([^~]*?\\)" + ">>>>>>> [0-9a-f]\\{40\\}\n") + "\\2") From 767950fc9a757d2ba8f9a107e67061eda32ea724 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Wed, 17 Dec 2025 10:51:05 -0800 Subject: [PATCH 38/82] Add more exports --- make/CompileInterimLangtools.gmk | 4 +++- make/langtools/tools/javacserver/shared/PortFile.java | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/make/CompileInterimLangtools.gmk b/make/CompileInterimLangtools.gmk index 516a7fedba0..f8266eaae0b 100644 --- a/make/CompileInterimLangtools.gmk +++ b/make/CompileInterimLangtools.gmk @@ -121,7 +121,9 @@ define SetupInterimModule --add-exports java.base/org.checkerframework.checker.builder.qual=jdk.compiler.interim \ --add-exports java.base/org.checkerframework.checker.builder.qual=jdk.javadoc.interim \ --add-exports java.base/org.checkerframework.checker.builder.qual=javacserver.shared \ - --add-exports java.base/org.checkerframework.checker.builder.qual=build.tools.pandocfilter.json \ + --add-exports java.base/org.checkerframework.checker.nullness.qual=build.tools.pandocfilter.json \ + --add-exports java.base/org.checkerframework.dataflow.qual=build.tools.pandocfilter.json \ + --add-exports java.base/org.checkerframework.dataflow.qual=javacserver.shared \ --add-exports jdk.internal.opt/jdk.internal.opt=jdk.compiler.interim \ --add-exports jdk.internal.opt/jdk.internal.opt=jdk.javadoc.interim, \ )) diff --git a/make/langtools/tools/javacserver/shared/PortFile.java b/make/langtools/tools/javacserver/shared/PortFile.java index 497069ee261..53ce4cb58e1 100644 --- a/make/langtools/tools/javacserver/shared/PortFile.java +++ b/make/langtools/tools/javacserver/shared/PortFile.java @@ -25,7 +25,7 @@ package javacserver.shared; -// import org.checkerframework.dataflow.qual.Pure; +import org.checkerframework.dataflow.qual.Pure; import java.io.File; import java.io.FileNotFoundException; @@ -136,7 +136,8 @@ public void getValues() { /** * Did the locking and getValues succeed? */ - // @Pure + + @Pure public boolean containsPortInfo() { return containsPortInfo; } From 97f8124ddd08db24d712949871f4dbe934ccc6fc Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Wed, 17 Dec 2025 11:18:26 -0800 Subject: [PATCH 39/82] Comment out an annotation --- make/langtools/tools/javacserver/shared/PortFile.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/make/langtools/tools/javacserver/shared/PortFile.java b/make/langtools/tools/javacserver/shared/PortFile.java index 53ce4cb58e1..25da9c49396 100644 --- a/make/langtools/tools/javacserver/shared/PortFile.java +++ b/make/langtools/tools/javacserver/shared/PortFile.java @@ -25,7 +25,7 @@ package javacserver.shared; -import org.checkerframework.dataflow.qual.Pure; +// import org.checkerframework.dataflow.qual.Pure; import java.io.File; import java.io.FileNotFoundException; @@ -137,7 +137,7 @@ public void getValues() { * Did the locking and getValues succeed? */ - @Pure + // @Pure public boolean containsPortInfo() { return containsPortInfo; } From 0d14117ffd713e43a5f92d5a8928a5191cf08113 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Wed, 17 Dec 2025 15:20:48 -0800 Subject: [PATCH 40/82] Remove unused import statements --- .../classes/build/tools/pandocfilter/json/JSONNumber.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/make/jdk/src/classes/build/tools/pandocfilter/json/JSONNumber.java b/make/jdk/src/classes/build/tools/pandocfilter/json/JSONNumber.java index 00008fd546c..e5f9a0075c7 100644 --- a/make/jdk/src/classes/build/tools/pandocfilter/json/JSONNumber.java +++ b/make/jdk/src/classes/build/tools/pandocfilter/json/JSONNumber.java @@ -22,12 +22,6 @@ */ package build.tools.pandocfilter.json; -import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.SideEffectFree; - public class JSONNumber implements JSONValue { private long value; From 47f798c1ceeb6f900151a60b79334d7fdd49dec4 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 19 Dec 2025 00:50:18 -0800 Subject: [PATCH 41/82] Annotate recently-added APIs --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 9cfb35639ad..bc64fed51a3 100644 --- a/README.md +++ b/README.md @@ -219,9 +219,17 @@ git pull ../jdk-fork-${USER}-branch-jdk21 Push and wait for CI to pass. +Find all `.java` files that contain both `@AnnotatedFor` and a relevant `@since` +in Javadoc. For example, the regex "@since[ \t](18|19|20|21)". For each +relevant `@since`, add annotations for all the type systems in `@AnnotatedFor`. +Note: I have not yet done this for JDK 18-21. + DO NOT squash-and-merge the pull request. Both the jdk and jdk21u repositories need to be merged, retaining history. +For Michael Ernst only: update `~/bin/src/mdedots/share/mdevcupdate` +to refer to jdk21u, not jdk17u. + ## Design The goal of this repository is to write Checker Framework annotations in From bb3fec71bc7ebabb93fb2b2bbd6e194b65605e20 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 2 Jan 2026 11:40:00 -0800 Subject: [PATCH 42/82] Move Emacs functions for merging --- README-merging.el | 106 +--------------------------------------------- 1 file changed, 1 insertion(+), 105 deletions(-) diff --git a/README-merging.el b/README-merging.el index 03c5eac98df..5b657bd00aa 100644 --- a/README-merging.el +++ b/README-merging.el @@ -1,105 +1 @@ -;; This file contains editor commands that are helpful when merging the JDK. - -;; Run at the top level: etags $(rg --files-with-matches '<<<<<<') -;; Then, visit that tags table and run these expressions. - -;; To fix Java array declarations from -;; "short a2[]" to "short[] a2" or from -;; "@PolySigned short a2 @Nullable []" to "@PolySigned short @Nullable [] a2": -(tags-query-replace "\\([^@]\\)\\b\\([A-Z][a-z][A-Za-z0-9]+\\|byte\\|short\\|int\\|long\\|float\\|double\\|boolean\\|char\\) \\([A-Za-z0-9]+\\)\\(\\( ?@[A-Za-z0-9]+ ?\\)*\\[\\]\\)" "\\1\\2\\4 \\3") - -(defvar annotation-line-regex) -(setq annotation-line-regex - " *@\\(CallerSensitive\\|ForceInline\\|Override\\|Covariant({[0-9]})\\|CreatesMustCallFor\\|Deterministic\\|EqualsMethod\\|ForName\\|FormatMethod\\|GetConstructor\\|GetClass\\|GetMethod\\|InheritableMustCall(.*)\\|I18nMakeFormat\\|Invoke\\|MayReleaseLocks\\|MustCall(.*)\\|NewInstance\\|NotOwning\\|OptionalCreator\\|OptionalEliminator\\|OptionalPropagator\\|PolyUIEffect\\|PolyUIType\\|Pure\\|ReleasesNoLocks\\|SafeEffect\\|SideEffectFree\\|SideEffectsOnly.*\\|StaticallyExecutable\\|TerminatesExecution\\|UIEffect\\|UIPackage\\|UIType\\|UsesObjectEquals\\|CFComment(.*)\\|Ensures.*\\|Requires.*\\|AnnotatedFor.*\\)") - -;; Move annotations only on the HEAD method before the hunk. -(tags-query-replace - ;; "\\|SuppressWarnings.*" intentionally omitted; it should be the last annotation and should be resolved by hand. - (concat "^\\(<<<<<<< HEAD\n\\)\\(\\(" annotation-line-regex "\n\\)+\\)") - "\\2\\1") - -;; Move annotations only on the OTHER method before the hunk. -(tags-query-replace - (concat "^\\(<<<<<<< HEAD\n[^|]*\n|||||||.*\n[^=]*=======\n\\)\\(\\(?:" annotation-line-regex "\n\\)+\\)") - "\\2\\1") - -;; Move Checker Framework imports before the hunk. -(tags-query-replace - "^\\(<<<<<<< HEAD\n\\)\\(\\(import org.checkerframework..*;\n\\)+\n\\)" - "\\2\\1") - - -;; Resolve the first line of a diff, when HEAD has been edited. -;; This version requires "public" at start of \2 and \4. -(tags-query-replace - (concat - "^\\(<<<<<<< HEAD\n\\)" - "\\( *public .*\n\\)" - "\\(\\(?:\\(?:[^|\n][^\n]*\\)?\n\\)*|||||||.*\n\\)" - "\\( *public .*\n\\)" - "\\(\\(?:\\(?:[^=\n][^\n]*\\)?\n\\)*=======\n\\)" - "\\4") - "\\2\\1\\3\\5") -;; The more general version, which I don't seem to need. -(tags-query-replace - (concat - "^\\(<<<<<<< HEAD\n\\)" - "\\(.*\n\\)" - "\\([^|]*\n|||||||.*\n\\)" - "\\(.*\n\\)" - "\\([^=]*\n=======\n\\)" - "\\4") - "\\2\\1\\3\\5") - -;; Resolve the first line of a diff, when OTHER has been edited. -;; This version requires "public" at start of \2 and \4. -(tags-query-replace - (concat - "^\\(<<<<<<< HEAD\n\\)" - "\\( *public .*\n\\)" - "\\(\\(?:\\(?:[^|\n][^\n]*\\)?\n\\)*|||||||.*\n\\)" - "\\2" - "\\(\\(?:\\(?:[^=\n][^\n]*\\)?\n\\)*=======\n\\)" - "\\( *public .*\n\\)") - "\\5\\1\\3\\4") - -;; Special case for the `equals()` method. -(tags-query-replace - (concat - "<<<<<<< HEAD\n" - " public boolean equals(Object obj) {\n" - "||||||| [0-9a-f]\\{11\\}\n" - " public boolean equals(Object obj) {\n" - "=======\n" - " public boolean equals(@Nullable Object obj) {\n" - ">>>>>>> [0-9a-f]\\{40\\}\n") - " public boolean equals(@Nullable Object obj) {\n") - -;; Resolve completely empty diffs. -(tags-query-replace - (concat - "<<<<<<< HEAD\n" - "||||||| [0-9a-f]\\{11\\}\n" - "=======\n" - ">>>>>>> [0-9a-f]\\{40\\}\n") - "") - -;; Resolve diffs where one of the ancestors is empty. -(tags-query-replace - (concat - "<<<<<<< HEAD\n" - "||||||| [0-9a-f]\\{11\\}\n" - "=======\n" - "\\([^~]*?\\)\n" - ">>>>>>> [0-9a-f]\\{40\\}\n") - "\\1") -(tags-query-replace - (concat - "<<<<<<< HEAD\n" - "\\([^~]*?\n\\)" - "||||||| [0-9a-f]\\{11\\}\n" - "\\1" - "=======\n" - "\\([^~]*?\\)" - ">>>>>>> [0-9a-f]\\{40\\}\n") - "\\2") +;; See file diff-resolve.el From bcc41427deff7a308f844d46b26c37b5f281d6c7 Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Wed, 22 Apr 2026 15:26:48 -0400 Subject: [PATCH 43/82] `Pattern`: use `PolyRegex` for receiver and return of `pattern` and `toString` (#132) --- src/java.base/share/classes/java/util/regex/Pattern.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/util/regex/Pattern.java b/src/java.base/share/classes/java/util/regex/Pattern.java index 86befd977ec..fbb8f5f4514 100644 --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -1119,7 +1119,7 @@ public static Pattern compile(@Regex String regex, int flags) { * @return The source of this pattern */ @Pure - public String pattern() { + public @PolyRegex String pattern(@PolyRegex Pattern this) { return pattern; } @@ -1132,7 +1132,7 @@ public String pattern() { * @since 1.5 */ @Pure - public String toString(@GuardSatisfied Pattern this) { + public @PolyRegex String toString(@GuardSatisfied @PolyRegex Pattern this) { return pattern; } From ba00819edba7409dd0812e8156804394e884ef57 Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Mon, 31 Aug 2026 05:36:31 -0400 Subject: [PATCH 44/82] Add `@EnsuresInitialized` postcondition (#136) --- .../qual/EnsuresInitialized.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/java.base/share/classes/org/checkerframework/checker/initialization/qual/EnsuresInitialized.java diff --git a/src/java.base/share/classes/org/checkerframework/checker/initialization/qual/EnsuresInitialized.java b/src/java.base/share/classes/org/checkerframework/checker/initialization/qual/EnsuresInitialized.java new file mode 100644 index 00000000000..811c76c137a --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/initialization/qual/EnsuresInitialized.java @@ -0,0 +1,62 @@ +package org.checkerframework.checker.initialization.qual; + +import org.checkerframework.framework.qual.InheritedAnnotation; +import org.checkerframework.framework.qual.PostconditionAnnotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * A method postcondition annotation that guarantees that the given Java expressions are {@link + * Initialized} after the method terminates successfully. + * + *

      This annotation is useful when a method initializes a field of an object that is currently + * {@link UnderInitialization} (or {@link UnknownInitialization}). It tells the Initialization + * Checker that the field has been assigned a value. + * + *

      If the receiver is already fully {@link Initialized}, this annotation provides no new + * information and is trivially true. If you also want to guarantee that a reference field is not + * null (for the Nullness Checker), use {@link + * org.checkerframework.checker.nullness.qual.EnsuresNonNull} instead, which implies initialization + * but also provides a nullness guarantee. + * + *

      Note: This is an Initialization Checker postcondition, distinct from {@link + * org.checkerframework.common.initializedfields.qual.EnsuresInitializedFields} which is used by the + * standalone Initialized Fields Checker. + * + * @checker_framework.manual #initialization-checker Initialization Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) +@PostconditionAnnotation(qualifier = Initialized.class) +@InheritedAnnotation +@Repeatable(EnsuresInitialized.List.class) +public @interface EnsuresInitialized { + /** + * The Java expressions that are initialized upon successful method termination. + * + * @return the Java expressions that are initialized + * @checker_framework.manual #java-expressions-as-arguments Syntax of Java expressions + */ + String[] value(); + + /** A wrapper annotation that makes the {@link EnsuresInitialized} annotation repeatable. */ + @Documented + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) + @PostconditionAnnotation(qualifier = Initialized.class) + @InheritedAnnotation + public static @interface List { + /** + * Return the repeatable annotations. + * + * @return the repeatable annotations + */ + EnsuresInitialized[] value(); + } +} From 3bd57ab184286012692c11b4fbc88f631719fe0e Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Mon, 31 Aug 2026 19:03:28 +0200 Subject: [PATCH 45/82] Annotate Queue, Deque, and BlockingDeque peek methods with `@Pure` (#137) --- src/java.base/share/classes/java/util/Deque.java | 9 ++++++--- src/java.base/share/classes/java/util/Queue.java | 3 ++- .../classes/java/util/concurrent/BlockingDeque.java | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/java/util/Deque.java b/src/java.base/share/classes/java/util/Deque.java index c538662e94b..b39965ec69b 100644 --- a/src/java.base/share/classes/java/util/Deque.java +++ b/src/java.base/share/classes/java/util/Deque.java @@ -359,7 +359,8 @@ public interface Deque extends Queue { * * @return the head of this deque, or {@code null} if this deque is empty */ - @Nullable E peekFirst(); + @Pure + @Nullable E peekFirst(@GuardSatisfied Deque this); /** * Retrieves, but does not remove, the last element of this deque, @@ -367,7 +368,8 @@ public interface Deque extends Queue { * * @return the tail of this deque, or {@code null} if this deque is empty */ - @Nullable E peekLast(); + @Pure + @Nullable E peekLast(@GuardSatisfied Deque this); /** * Removes the first occurrence of the specified element from this deque. @@ -505,7 +507,8 @@ public interface Deque extends Queue { * @return the head of the queue represented by this deque, or * {@code null} if this deque is empty */ - @Nullable E peek(); + @Pure + @Nullable E peek(@GuardSatisfied Deque this); /** * Adds all of the elements in the specified collection at the end diff --git a/src/java.base/share/classes/java/util/Queue.java b/src/java.base/share/classes/java/util/Queue.java index 0c7343acc26..e72a674119e 100644 --- a/src/java.base/share/classes/java/util/Queue.java +++ b/src/java.base/share/classes/java/util/Queue.java @@ -220,7 +220,8 @@ public interface Queue extends Collection { * * @return the head of this queue, or {@code null} if this queue is empty */ - @Nullable E peek(); + @Pure + @Nullable E peek(@GuardSatisfied Queue this); @CFComment("Copied from Collection to make it annotatable") @Pure diff --git a/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java b/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java index 2180e76e280..19c69c78465 100644 --- a/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java @@ -589,6 +589,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * * @return the head of this deque, or {@code null} if this deque is empty */ + @Pure @Nullable E peek(); /** From 0fe3a5c78765483420f40b61e875086392f59065 Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Mon, 7 Sep 2026 16:06:45 -0400 Subject: [PATCH 46/82] Add subpackage controls to package annotations (#138) --- .../common/util/report/qual/ReportUse.java | 18 ++++++++++++++++-- .../framework/qual/AnnotatedFor.java | 11 +++++++++++ .../framework/qual/HasQualifierParameter.java | 15 ++++++++++++--- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/org/checkerframework/common/util/report/qual/ReportUse.java b/src/java.base/share/classes/org/checkerframework/common/util/report/qual/ReportUse.java index 91b7f646529..b9077e2a005 100644 --- a/src/java.base/share/classes/org/checkerframework/common/util/report/qual/ReportUse.java +++ b/src/java.base/share/classes/org/checkerframework/common/util/report/qual/ReportUse.java @@ -6,8 +6,22 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** Report all uses of a type that has this annotation. Can also be used on a package. */ +/** + * Report all uses of a type that has this annotation. Can also be used on a package. + * + *

      When written on a package, {@code @ReportUse} applies to that package and its subpackages by + * default. Set {@link #applyToSubpackages()} to false to limit it to the package itself; doing so + * does not block an applicable {@code @ReportUse} on an enclosing package. + */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PACKAGE, ElementType.TYPE}) -public @interface ReportUse {} +public @interface ReportUse { + + /** + * When used on a package, whether this annotation should also apply to subpackages. + * + * @return whether this annotation should be inherited by subpackages + */ + boolean applyToSubpackages() default true; +} diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/AnnotatedFor.java b/src/java.base/share/classes/org/checkerframework/framework/qual/AnnotatedFor.java index 48c4f7ab47f..05da2f4138b 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/AnnotatedFor.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/AnnotatedFor.java @@ -23,6 +23,10 @@ * warnings. However, a class with a relevant {@code @AnnotatedFor} annotation is always defaulted * normally (typically using the CLIMB-to-top rule), and typechecking warnings are issued. * + *

      An {@code @AnnotatedFor} on a package also applies to subpackages, unless the {@code + * applyToSubpackages} field is set to false. Setting it to false does not block an applicable + * {@code @AnnotatedFor} on an enclosing package. + * * @checker_framework.manual #compiling-libraries Compiling partially-annotated libraries */ @Documented @@ -39,4 +43,11 @@ * @checker_framework.manual #shorthand-for-checkers Short names for built-in checkers */ String[] value(); + + /** + * When used on a package, whether this annotation should also apply to subpackages. + * + * @return whether this annotation should be inherited by subpackages + */ + boolean applyToSubpackages() default true; } diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/HasQualifierParameter.java b/src/java.base/share/classes/org/checkerframework/framework/qual/HasQualifierParameter.java index cd59052d2f5..7f1cb3c6eed 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/HasQualifierParameter.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/HasQualifierParameter.java @@ -63,9 +63,11 @@ *

      Written on a package

      * *

      When {@code @HasQualifierParameter} is written on a package, it is equivalent to writing that - * annotation on each class in the package or in a sub-package. It can be disabled on a specific - * class and its subclasses by writing {@code @NoQualifierParameter} on that class. This annotation - * may not be written on the same class as {@code NoQualifierParameter} for the same hierarchy. + * annotation on each class in the package or in a sub-package. Set the {@code applyToSubpackages} + * field to false to limit it to the package itself; doing so does not block an applicable + * {@code @HasQualifierParameter} on an enclosing package. It can be disabled on a specific class + * and its subclasses by writing {@code @NoQualifierParameter} on that class. This annotation may + * not be written on the same class as {@code @NoQualifierParameter} for the same hierarchy. * * @see NoQualifierParameter */ @@ -81,4 +83,11 @@ * @return the value */ Class[] value(); + + /** + * When used on a package, whether this annotation should also apply to subpackages. + * + * @return whether this annotation should be inherited by subpackages + */ + boolean applyToSubpackages() default true; } From 96eb53bacb6a044404b25fa9bfa0ce73d46be8f7 Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Wed, 9 Sep 2026 17:29:44 -0400 Subject: [PATCH 47/82] Annotate 16 exception classes for nullness (#139) Co-authored-by: Claude Opus 5 --- src/java.base/share/classes/java/io/IOError.java | 6 +++++- .../classes/java/lang/IllegalCallerException.java | 10 +++++++--- .../java/lang/LayerInstantiationException.java | 10 +++++++--- .../java/lang/ReflectiveOperationException.java | 10 +++++++--- .../java/lang/invoke/LambdaConversionException.java | 12 ++++++++---- .../java/lang/invoke/StringConcatException.java | 8 ++++++-- .../java/lang/invoke/WrongMethodTypeException.java | 10 +++++++--- .../classes/java/lang/module/FindException.java | 10 +++++++--- .../java/lang/module/ResolutionException.java | 10 +++++++--- .../java/util/ConcurrentModificationException.java | 10 +++++++--- .../java/util/InvalidPropertiesFormatException.java | 7 +++++-- .../classes/java/util/MissingResourceException.java | 8 ++++++-- .../classes/java/util/NoSuchElementException.java | 10 +++++++--- .../classes/java/util/ServiceConfigurationError.java | 8 ++++++-- .../java/util/concurrent/CompletionException.java | 10 +++++++--- .../util/concurrent/RejectedExecutionException.java | 10 +++++++--- 16 files changed, 106 insertions(+), 43 deletions(-) diff --git a/src/java.base/share/classes/java/io/IOError.java b/src/java.base/share/classes/java/io/IOError.java index 622143db9a8..bd5ca7d7e64 100644 --- a/src/java.base/share/classes/java/io/IOError.java +++ b/src/java.base/share/classes/java/io/IOError.java @@ -25,12 +25,16 @@ package java.io; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Thrown when a serious I/O error has occurred. * * @author Xueming Shen * @since 1.6 */ +@AnnotatedFor({"nullness"}) public class IOError extends Error { /** * Constructs a new instance of IOError with the specified cause. The @@ -42,7 +46,7 @@ public class IOError extends Error { * The cause of this error, or {@code null} if the cause * is not known */ - public IOError(Throwable cause) { + public IOError(@Nullable Throwable cause) { super(cause); } diff --git a/src/java.base/share/classes/java/lang/IllegalCallerException.java b/src/java.base/share/classes/java/lang/IllegalCallerException.java index 68c3ff00d9f..e0d1f355a98 100644 --- a/src/java.base/share/classes/java/lang/IllegalCallerException.java +++ b/src/java.base/share/classes/java/lang/IllegalCallerException.java @@ -25,12 +25,16 @@ package java.lang; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Thrown to indicate that a method has been called by an inappropriate caller. * * @since 9 * @see StackWalker#getCallerClass */ +@AnnotatedFor({"nullness"}) public class IllegalCallerException extends RuntimeException { /** * Constructs an IllegalCallerException with no detail message. @@ -45,7 +49,7 @@ public IllegalCallerException() { * * @param s the String that contains a detailed message (can be null) */ - public IllegalCallerException(String s) { + public IllegalCallerException(@Nullable String s) { super(s); } @@ -56,7 +60,7 @@ public IllegalCallerException(String s) { * @param message the detail message (can be null) * @param cause the cause (can be null) */ - public IllegalCallerException(String message, Throwable cause) { + public IllegalCallerException(@Nullable String message, @Nullable Throwable cause) { super(message, cause); } @@ -67,7 +71,7 @@ public IllegalCallerException(String message, Throwable cause) { * * @param cause the cause (can be null) */ - public IllegalCallerException(Throwable cause) { + public IllegalCallerException(@Nullable Throwable cause) { super(cause); } diff --git a/src/java.base/share/classes/java/lang/LayerInstantiationException.java b/src/java.base/share/classes/java/lang/LayerInstantiationException.java index 6c1469df79b..ad86fb4745d 100644 --- a/src/java.base/share/classes/java/lang/LayerInstantiationException.java +++ b/src/java.base/share/classes/java/lang/LayerInstantiationException.java @@ -25,12 +25,16 @@ package java.lang; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Thrown when creating a {@linkplain ModuleLayer module layer} fails. * * @see ModuleLayer * @since 9 */ +@AnnotatedFor({"nullness"}) public class LayerInstantiationException extends RuntimeException { @java.io.Serial private static final long serialVersionUID = -906239691613568347L; @@ -48,7 +52,7 @@ public LayerInstantiationException() { * @param msg * The detail message; can be {@code null} */ - public LayerInstantiationException(String msg) { + public LayerInstantiationException(@Nullable String msg) { super(msg); } @@ -58,7 +62,7 @@ public LayerInstantiationException(String msg) { * @param cause * The cause; can be {@code null} */ - public LayerInstantiationException(Throwable cause) { + public LayerInstantiationException(@Nullable Throwable cause) { super(cause); } @@ -71,7 +75,7 @@ public LayerInstantiationException(Throwable cause) { * @param cause * The cause; can be {@code null} */ - public LayerInstantiationException(String msg, Throwable cause) { + public LayerInstantiationException(@Nullable String msg, @Nullable Throwable cause) { super(msg, cause); } } diff --git a/src/java.base/share/classes/java/lang/ReflectiveOperationException.java b/src/java.base/share/classes/java/lang/ReflectiveOperationException.java index 0c79de008be..fe27804a775 100644 --- a/src/java.base/share/classes/java/lang/ReflectiveOperationException.java +++ b/src/java.base/share/classes/java/lang/ReflectiveOperationException.java @@ -25,6 +25,9 @@ package java.lang; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Common superclass of exceptions thrown by reflective operations in * core reflection. @@ -32,6 +35,7 @@ * @see LinkageError * @since 1.7 */ +@AnnotatedFor({"nullness"}) public class ReflectiveOperationException extends Exception { @java.io.Serial static final long serialVersionUID = 123456789L; @@ -53,7 +57,7 @@ public ReflectiveOperationException() { * @param message the detail message. The detail message is saved for * later retrieval by the {@link #getMessage()} method. */ - public ReflectiveOperationException(String message) { + public ReflectiveOperationException(@Nullable String message) { super(message); } @@ -72,7 +76,7 @@ public ReflectiveOperationException(String message) { * permitted, and indicates that the cause is nonexistent or * unknown.) */ - public ReflectiveOperationException(String message, Throwable cause) { + public ReflectiveOperationException(@Nullable String message, @Nullable Throwable cause) { super(message, cause); } @@ -86,7 +90,7 @@ public ReflectiveOperationException(String message, Throwable cause) { * permitted, and indicates that the cause is nonexistent or * unknown.) */ - public ReflectiveOperationException(Throwable cause) { + public ReflectiveOperationException(@Nullable Throwable cause) { super(cause); } } diff --git a/src/java.base/share/classes/java/lang/invoke/LambdaConversionException.java b/src/java.base/share/classes/java/lang/invoke/LambdaConversionException.java index f3950c47c16..a1ecdcee651 100644 --- a/src/java.base/share/classes/java/lang/invoke/LambdaConversionException.java +++ b/src/java.base/share/classes/java/lang/invoke/LambdaConversionException.java @@ -25,11 +25,15 @@ package java.lang.invoke; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * LambdaConversionException * * @since 1.8 */ +@AnnotatedFor({"nullness"}) public class LambdaConversionException extends Exception { @java.io.Serial private static final long serialVersionUID = 292L + 8L; @@ -44,7 +48,7 @@ public LambdaConversionException() { * Constructs a {@code LambdaConversionException} with a message. * @param message the detail message */ - public LambdaConversionException(String message) { + public LambdaConversionException(@Nullable String message) { super(message); } @@ -53,7 +57,7 @@ public LambdaConversionException(String message) { * @param message the detail message * @param cause the cause */ - public LambdaConversionException(String message, Throwable cause) { + public LambdaConversionException(@Nullable String message, @Nullable Throwable cause) { super(message, cause); } @@ -61,7 +65,7 @@ public LambdaConversionException(String message, Throwable cause) { * Constructs a {@code LambdaConversionException} with a cause. * @param cause the cause */ - public LambdaConversionException(Throwable cause) { + public LambdaConversionException(@Nullable Throwable cause) { super(cause); } @@ -73,7 +77,7 @@ public LambdaConversionException(Throwable cause) { * @param enableSuppression whether or not suppressed exceptions are enabled * @param writableStackTrace whether or not the stack trace is writable */ - public LambdaConversionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + public LambdaConversionException(@Nullable String message, @Nullable Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } } diff --git a/src/java.base/share/classes/java/lang/invoke/StringConcatException.java b/src/java.base/share/classes/java/lang/invoke/StringConcatException.java index 575e0019329..80fa794c783 100644 --- a/src/java.base/share/classes/java/lang/invoke/StringConcatException.java +++ b/src/java.base/share/classes/java/lang/invoke/StringConcatException.java @@ -25,12 +25,16 @@ package java.lang.invoke; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * StringConcatException is thrown by {@link StringConcatFactory} when linkage * invariants are violated. * * @since 9 */ +@AnnotatedFor({"nullness"}) public class StringConcatException extends Exception { @java.io.Serial private static final long serialVersionUID = 292L + 9L; @@ -39,7 +43,7 @@ public class StringConcatException extends Exception { * Constructs an exception with a message * @param msg exception message */ - public StringConcatException(String msg) { + public StringConcatException(@Nullable String msg) { super(msg); } @@ -48,7 +52,7 @@ public StringConcatException(String msg) { * @param msg exception message * @param cause throwable cause */ - public StringConcatException(String msg, Throwable cause) { + public StringConcatException(@Nullable String msg, @Nullable Throwable cause) { super(msg, cause); } } diff --git a/src/java.base/share/classes/java/lang/invoke/WrongMethodTypeException.java b/src/java.base/share/classes/java/lang/invoke/WrongMethodTypeException.java index e7dfa83900a..e09370ebeb4 100644 --- a/src/java.base/share/classes/java/lang/invoke/WrongMethodTypeException.java +++ b/src/java.base/share/classes/java/lang/invoke/WrongMethodTypeException.java @@ -25,6 +25,9 @@ package java.lang.invoke; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Thrown to indicate that code has attempted to call a method handle * via the wrong method type. As with the bytecode representation of @@ -40,6 +43,7 @@ * @author John Rose, JSR 292 EG * @since 1.7 */ +@AnnotatedFor({"nullness"}) public class WrongMethodTypeException extends RuntimeException { @java.io.Serial private static final long serialVersionUID = 292L; @@ -57,7 +61,7 @@ public WrongMethodTypeException() { * * @param s the detail message. */ - public WrongMethodTypeException(String s) { + public WrongMethodTypeException(@Nullable String s) { super(s); } @@ -70,7 +74,7 @@ public WrongMethodTypeException(String s) { */ //FIXME: make this public in MR1 /*non-public*/ - WrongMethodTypeException(String s, Throwable cause) { + WrongMethodTypeException(@Nullable String s, @Nullable Throwable cause) { super(s, cause); } @@ -82,7 +86,7 @@ public WrongMethodTypeException(String s) { */ //FIXME: make this public in MR1 /*non-public*/ - WrongMethodTypeException(Throwable cause) { + WrongMethodTypeException(@Nullable Throwable cause) { super(cause); } } diff --git a/src/java.base/share/classes/java/lang/module/FindException.java b/src/java.base/share/classes/java/lang/module/FindException.java index 71bea3e94b1..f0c22e5a0b1 100644 --- a/src/java.base/share/classes/java/lang/module/FindException.java +++ b/src/java.base/share/classes/java/lang/module/FindException.java @@ -25,6 +25,9 @@ package java.lang.module; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Thrown by a {@link ModuleFinder ModuleFinder} when an error occurs finding * a module. Also thrown by {@link @@ -35,6 +38,7 @@ * @since 9 */ +@AnnotatedFor({"nullness"}) public class FindException extends RuntimeException { @java.io.Serial private static final long serialVersionUID = -5817081036963388391L; @@ -52,7 +56,7 @@ public FindException() { * @param msg * The detail message; can be {@code null} */ - public FindException(String msg) { + public FindException(@Nullable String msg) { super(msg); } @@ -62,7 +66,7 @@ public FindException(String msg) { * @param cause * The cause; can be {@code null} */ - public FindException(Throwable cause) { + public FindException(@Nullable Throwable cause) { super(cause); } @@ -75,7 +79,7 @@ public FindException(Throwable cause) { * @param cause * The cause; can be {@code null} */ - public FindException(String msg, Throwable cause) { + public FindException(@Nullable String msg, @Nullable Throwable cause) { super(msg, cause); } } diff --git a/src/java.base/share/classes/java/lang/module/ResolutionException.java b/src/java.base/share/classes/java/lang/module/ResolutionException.java index b9b96b70acb..7340fef8850 100644 --- a/src/java.base/share/classes/java/lang/module/ResolutionException.java +++ b/src/java.base/share/classes/java/lang/module/ResolutionException.java @@ -25,6 +25,9 @@ package java.lang.module; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Thrown when resolving a set of modules, or resolving a set of modules with * service binding, fails. @@ -32,6 +35,7 @@ * @see Configuration * @since 9 */ +@AnnotatedFor({"nullness"}) public class ResolutionException extends RuntimeException { @java.io.Serial private static final long serialVersionUID = -1031186845316729450L; @@ -48,7 +52,7 @@ public ResolutionException() { } * @param msg * The detail message; can be {@code null} */ - public ResolutionException(String msg) { + public ResolutionException(@Nullable String msg) { super(msg); } @@ -58,7 +62,7 @@ public ResolutionException(String msg) { * @param cause * The cause; can be {@code null} */ - public ResolutionException(Throwable cause) { + public ResolutionException(@Nullable Throwable cause) { super(cause); } @@ -71,7 +75,7 @@ public ResolutionException(Throwable cause) { * @param cause * The cause; can be {@code null} */ - public ResolutionException(String msg, Throwable cause) { + public ResolutionException(@Nullable String msg, @Nullable Throwable cause) { super(msg, cause); } diff --git a/src/java.base/share/classes/java/util/ConcurrentModificationException.java b/src/java.base/share/classes/java/util/ConcurrentModificationException.java index 7161225bad4..4cb5999265c 100644 --- a/src/java.base/share/classes/java/util/ConcurrentModificationException.java +++ b/src/java.base/share/classes/java/util/ConcurrentModificationException.java @@ -25,6 +25,9 @@ package java.util; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * This exception may be thrown by methods that have detected concurrent * modification of an object when such modification is not permissible. @@ -67,6 +70,7 @@ * @see AbstractList * @since 1.2 */ +@AnnotatedFor({"nullness"}) public class ConcurrentModificationException extends RuntimeException { @java.io.Serial private static final long serialVersionUID = -3666751008965953603L; @@ -84,7 +88,7 @@ public ConcurrentModificationException() { * * @param message the detail message pertaining to this exception. */ - public ConcurrentModificationException(String message) { + public ConcurrentModificationException(@Nullable String message) { super(message); } @@ -99,7 +103,7 @@ public ConcurrentModificationException(String message) { * unknown.) * @since 1.7 */ - public ConcurrentModificationException(Throwable cause) { + public ConcurrentModificationException(@Nullable Throwable cause) { super(cause); } @@ -119,7 +123,7 @@ public ConcurrentModificationException(Throwable cause) { * unknown.) * @since 1.7 */ - public ConcurrentModificationException(String message, Throwable cause) { + public ConcurrentModificationException(@Nullable String message, @Nullable Throwable cause) { super(message, cause); } } diff --git a/src/java.base/share/classes/java/util/InvalidPropertiesFormatException.java b/src/java.base/share/classes/java/util/InvalidPropertiesFormatException.java index 3b1801b90fd..21814052fd5 100644 --- a/src/java.base/share/classes/java/util/InvalidPropertiesFormatException.java +++ b/src/java.base/share/classes/java/util/InvalidPropertiesFormatException.java @@ -27,6 +27,8 @@ import java.io.NotSerializableException; import java.io.IOException; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; /** * Thrown to indicate that an operation could not complete because @@ -43,6 +45,7 @@ * @serial exclude */ +@AnnotatedFor({"nullness"}) public class InvalidPropertiesFormatException extends IOException { @java.io.Serial @@ -55,7 +58,7 @@ public class InvalidPropertiesFormatException extends IOException { * @param cause the cause (which is saved for later retrieval by the * {@link Throwable#getCause()} method). */ - public InvalidPropertiesFormatException(Throwable cause) { + public InvalidPropertiesFormatException(@Nullable Throwable cause) { super(cause==null ? null : cause.toString()); this.initCause(cause); } @@ -67,7 +70,7 @@ public InvalidPropertiesFormatException(Throwable cause) { * @param message the detail message. The detail message is saved for * later retrieval by the {@link Throwable#getMessage()} method. */ - public InvalidPropertiesFormatException(String message) { + public InvalidPropertiesFormatException(@Nullable String message) { super(message); } diff --git a/src/java.base/share/classes/java/util/MissingResourceException.java b/src/java.base/share/classes/java/util/MissingResourceException.java index ea93fd82809..25c8877a5fa 100644 --- a/src/java.base/share/classes/java/util/MissingResourceException.java +++ b/src/java.base/share/classes/java/util/MissingResourceException.java @@ -40,6 +40,9 @@ package java.util; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Signals that a resource is missing. * @see java.lang.Exception @@ -47,6 +50,7 @@ * @author Mark Davis * @since 1.1 */ +@AnnotatedFor({"nullness"}) public class MissingResourceException extends RuntimeException { /** @@ -56,7 +60,7 @@ public class MissingResourceException extends RuntimeException { * @param className the name of the resource class * @param key the key for the missing resource. */ - public MissingResourceException(String s, String className, String key) { + public MissingResourceException(@Nullable String s, String className, String key) { super(s); this.className = className; this.key = key; @@ -80,7 +84,7 @@ public MissingResourceException(String s, String className, String key) { * permitted, and indicates that the cause is nonexistent * or unknown.) */ - MissingResourceException(String message, String className, String key, Throwable cause) { + MissingResourceException(@Nullable String message, String className, String key, @Nullable Throwable cause) { super(message, cause); this.className = className; this.key = key; diff --git a/src/java.base/share/classes/java/util/NoSuchElementException.java b/src/java.base/share/classes/java/util/NoSuchElementException.java index 28c20367958..332374c6461 100644 --- a/src/java.base/share/classes/java/util/NoSuchElementException.java +++ b/src/java.base/share/classes/java/util/NoSuchElementException.java @@ -25,6 +25,9 @@ package java.util; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Thrown by various accessor methods to indicate that the element being requested * does not exist. @@ -33,6 +36,7 @@ * @see java.util.Iterator#next() * @since 1.0 */ +@AnnotatedFor({"nullness"}) public class NoSuchElementException extends RuntimeException { @java.io.Serial private static final long serialVersionUID = 6769829250639411880L; @@ -54,7 +58,7 @@ public NoSuchElementException() { * {@link #getCause()} method), or null * @since 15 */ - public NoSuchElementException(String s, Throwable cause) { + public NoSuchElementException(@Nullable String s, @Nullable Throwable cause) { super(s, cause); } @@ -68,7 +72,7 @@ public NoSuchElementException(String s, Throwable cause) { * {@link #getCause()} method) * @since 15 */ - public NoSuchElementException(Throwable cause) { + public NoSuchElementException(@Nullable Throwable cause) { super(cause); } @@ -79,7 +83,7 @@ public NoSuchElementException(Throwable cause) { * * @param s the detail message. */ - public NoSuchElementException(String s) { + public NoSuchElementException(@Nullable String s) { super(s); } } diff --git a/src/java.base/share/classes/java/util/ServiceConfigurationError.java b/src/java.base/share/classes/java/util/ServiceConfigurationError.java index 0645f00d125..4144fcded18 100644 --- a/src/java.base/share/classes/java/util/ServiceConfigurationError.java +++ b/src/java.base/share/classes/java/util/ServiceConfigurationError.java @@ -25,6 +25,9 @@ package java.util; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Error thrown when something goes wrong while locating, loading, or @@ -35,6 +38,7 @@ * @see ServiceLoader */ +@AnnotatedFor({"nullness"}) public class ServiceConfigurationError extends Error { @@ -48,7 +52,7 @@ public class ServiceConfigurationError * @param msg The message, or {@code null} if there is no message * */ - public ServiceConfigurationError(String msg) { + public ServiceConfigurationError(@Nullable String msg) { super(msg); } @@ -60,7 +64,7 @@ public ServiceConfigurationError(String msg) { * @param cause The cause, or {@code null} if the cause is nonexistent * or unknown */ - public ServiceConfigurationError(String msg, Throwable cause) { + public ServiceConfigurationError(@Nullable String msg, @Nullable Throwable cause) { super(msg, cause); } diff --git a/src/java.base/share/classes/java/util/concurrent/CompletionException.java b/src/java.base/share/classes/java/util/concurrent/CompletionException.java index 2a3cfc56adf..8a076475815 100644 --- a/src/java.base/share/classes/java/util/concurrent/CompletionException.java +++ b/src/java.base/share/classes/java/util/concurrent/CompletionException.java @@ -35,6 +35,9 @@ package java.util.concurrent; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Exception thrown when an error or other exception is encountered * in the course of completing a result or task. @@ -42,6 +45,7 @@ * @since 1.8 * @author Doug Lea */ +@AnnotatedFor({"nullness"}) public class CompletionException extends RuntimeException { private static final long serialVersionUID = 7830266012832686185L; @@ -59,7 +63,7 @@ protected CompletionException() { } * * @param message the detail message */ - protected CompletionException(String message) { + protected CompletionException(@Nullable String message) { super(message); } @@ -71,7 +75,7 @@ protected CompletionException(String message) { * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method) */ - public CompletionException(String message, Throwable cause) { + public CompletionException(@Nullable String message, @Nullable Throwable cause) { super(message, cause); } @@ -84,7 +88,7 @@ public CompletionException(String message, Throwable cause) { * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method) */ - public CompletionException(Throwable cause) { + public CompletionException(@Nullable Throwable cause) { super(cause); } } diff --git a/src/java.base/share/classes/java/util/concurrent/RejectedExecutionException.java b/src/java.base/share/classes/java/util/concurrent/RejectedExecutionException.java index 87feef49513..8529b89af11 100644 --- a/src/java.base/share/classes/java/util/concurrent/RejectedExecutionException.java +++ b/src/java.base/share/classes/java/util/concurrent/RejectedExecutionException.java @@ -35,6 +35,9 @@ package java.util.concurrent; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + /** * Exception thrown by an {@link Executor} when a task cannot be * accepted for execution. @@ -42,6 +45,7 @@ * @since 1.5 * @author Doug Lea */ +@AnnotatedFor({"nullness"}) public class RejectedExecutionException extends RuntimeException { private static final long serialVersionUID = -375805702767069545L; @@ -60,7 +64,7 @@ public RejectedExecutionException() { } * * @param message the detail message */ - public RejectedExecutionException(String message) { + public RejectedExecutionException(@Nullable String message) { super(message); } @@ -72,7 +76,7 @@ public RejectedExecutionException(String message) { * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method) */ - public RejectedExecutionException(String message, Throwable cause) { + public RejectedExecutionException(@Nullable String message, @Nullable Throwable cause) { super(message, cause); } @@ -85,7 +89,7 @@ public RejectedExecutionException(String message, Throwable cause) { * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method) */ - public RejectedExecutionException(Throwable cause) { + public RejectedExecutionException(@Nullable Throwable cause) { super(cause); } } From af731dd527bd87e8f2ddb94dd87d98fc92e09cbb Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Wed, 9 Sep 2026 20:02:23 -0400 Subject: [PATCH 48/82] Annotate VarHandle's reference read modes as @Nullable (#140) Co-authored-by: Claude Opus 5 --- .../classes/java/lang/invoke/VarHandle.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/java.base/share/classes/java/lang/invoke/VarHandle.java b/src/java.base/share/classes/java/lang/invoke/VarHandle.java index 89d9e7f75d2..16730732b37 100644 --- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java @@ -25,6 +25,9 @@ package java.lang.invoke; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + import java.lang.constant.ClassDesc; import java.lang.constant.Constable; import java.lang.constant.ConstantDesc; @@ -476,6 +479,7 @@ * @see MethodType * @since 9 */ +@AnnotatedFor({"nullness"}) public abstract class VarHandle implements Constable { final VarForm vform; final boolean exact; @@ -545,7 +549,7 @@ public boolean hasInvokeExactBehavior() { public final native @MethodHandle.PolymorphicSignature @IntrinsicCandidate - Object get(Object... args); + @Nullable Object get(Object... args); /** * Sets the value of a variable to the {@code newValue}, with memory @@ -603,7 +607,7 @@ public boolean hasInvokeExactBehavior() { public final native @MethodHandle.PolymorphicSignature @IntrinsicCandidate - Object getVolatile(Object... args); + @Nullable Object getVolatile(Object... args); /** * Sets the value of a variable to the {@code newValue}, with memory @@ -663,7 +667,7 @@ public boolean hasInvokeExactBehavior() { public final native @MethodHandle.PolymorphicSignature @IntrinsicCandidate - Object getOpaque(Object... args); + @Nullable Object getOpaque(Object... args); /** * Sets the value of a variable to the {@code newValue}, in program order, @@ -727,7 +731,7 @@ public boolean hasInvokeExactBehavior() { public final native @MethodHandle.PolymorphicSignature @IntrinsicCandidate - Object getAcquire(Object... args); + @Nullable Object getAcquire(Object... args); /** * Sets the value of a variable to the {@code newValue}, and ensures that @@ -829,7 +833,7 @@ public boolean hasInvokeExactBehavior() { public final native @MethodHandle.PolymorphicSignature @IntrinsicCandidate - Object compareAndExchange(Object... args); + @Nullable Object compareAndExchange(Object... args); /** * Atomically sets the value of a variable to the {@code newValue} with the @@ -864,7 +868,7 @@ public boolean hasInvokeExactBehavior() { public final native @MethodHandle.PolymorphicSignature @IntrinsicCandidate - Object compareAndExchangeAcquire(Object... args); + @Nullable Object compareAndExchangeAcquire(Object... args); /** * Atomically sets the value of a variable to the {@code newValue} with the @@ -899,7 +903,7 @@ public boolean hasInvokeExactBehavior() { public final native @MethodHandle.PolymorphicSignature @IntrinsicCandidate - Object compareAndExchangeRelease(Object... args); + @Nullable Object compareAndExchangeRelease(Object... args); // Weak (spurious failures allowed) @@ -1084,7 +1088,7 @@ public boolean hasInvokeExactBehavior() { public final native @MethodHandle.PolymorphicSignature @IntrinsicCandidate - Object getAndSet(Object... args); + @Nullable Object getAndSet(Object... args); /** * Atomically sets the value of a variable to the {@code newValue} with the @@ -1117,7 +1121,7 @@ public boolean hasInvokeExactBehavior() { public final native @MethodHandle.PolymorphicSignature @IntrinsicCandidate - Object getAndSetAcquire(Object... args); + @Nullable Object getAndSetAcquire(Object... args); /** * Atomically sets the value of a variable to the {@code newValue} with the @@ -1150,7 +1154,7 @@ public boolean hasInvokeExactBehavior() { public final native @MethodHandle.PolymorphicSignature @IntrinsicCandidate - Object getAndSetRelease(Object... args); + @Nullable Object getAndSetRelease(Object... args); // Primitive adders // Throw UnsupportedOperationException for refs From af6d72605d0bdf4b9c4ab91267de8f9d09db430e Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Wed, 9 Sep 2026 21:04:52 -0400 Subject: [PATCH 49/82] Annotate MethodHandle for nullness (#141) Co-authored-by: Claude Opus 5 --- .../classes/java/lang/invoke/MethodHandle.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java index c2e34a62e09..fd970310ecc 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java @@ -25,6 +25,9 @@ package java.lang.invoke; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.AnnotatedFor; + import jdk.internal.vm.annotation.IntrinsicCandidate; @@ -438,6 +441,7 @@ * @author John Rose, JSR 292 EG * @since 1.7 */ +@AnnotatedFor({"nullness"}) public abstract class MethodHandle implements Constable { /** @@ -499,7 +503,8 @@ public MethodType type() { * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call */ @IntrinsicCandidate - public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable; + public final native @PolymorphicSignature @Nullable Object invokeExact(Object... args) + throws Throwable; /** * Invokes the method handle, allowing any caller type descriptor, @@ -537,7 +542,8 @@ public MethodType type() { * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call */ @IntrinsicCandidate - public final native @PolymorphicSignature Object invoke(Object... args) throws Throwable; + public final native @PolymorphicSignature @Nullable Object invoke(Object... args) + throws Throwable; /** * Private method for trusted invocation of a method handle respecting simplified signatures. @@ -726,7 +732,7 @@ public MethodType type() { * @throws Throwable anything thrown by the target method invocation * @see MethodHandles#spreadInvoker */ - public Object invokeWithArguments(Object... arguments) throws Throwable { + public @Nullable Object invokeWithArguments(Object @Nullable ... arguments) throws Throwable { // Note: Jumbo argument lists are handled in the variable-arity subclass. MethodType invocationType = MethodType.genericMethodType(arguments == null ? 0 : arguments.length); return invocationType.invokers().spreadInvoker(0).invokeExact(asType(invocationType), arguments); @@ -753,7 +759,7 @@ public Object invokeWithArguments(Object... arguments) throws Throwable { * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the given number of {@code Object} arguments * @throws Throwable anything thrown by the target method invocation */ - public Object invokeWithArguments(java.util.List arguments) throws Throwable { + public @Nullable Object invokeWithArguments(java.util.List arguments) throws Throwable { return invokeWithArguments(arguments.toArray()); } From 33182bb7d88abde7c2647009173cc2db4341d9a6 Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Wed, 9 Sep 2026 21:33:07 -0400 Subject: [PATCH 50/82] Make `@AnnotatedFor` repeatable (#142) Co-authored-by: Claude Sonnet 5 --- .../framework/qual/AnnotatedFor.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/AnnotatedFor.java b/src/java.base/share/classes/org/checkerframework/framework/qual/AnnotatedFor.java index 05da2f4138b..c10c682b125 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/AnnotatedFor.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/AnnotatedFor.java @@ -2,6 +2,7 @@ import java.lang.annotation.Documented; import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -27,11 +28,21 @@ * applyToSubpackages} field is set to false. Setting it to false does not block an applicable * {@code @AnnotatedFor} on an enclosing package. * + *

      You may write multiple {@code @AnnotatedFor} annotations at the same location, for example to + * give two type systems different {@code applyToSubpackages} settings on one package: + * + *

      + *   {@literal @}AnnotatedFor(value = "nullness", applyToSubpackages = false)
      + *   {@literal @}AnnotatedFor(value = "index", applyToSubpackages = true)
      + *   package mypackage;
      + * 
      + * * @checker_framework.manual #compiling-libraries Compiling partially-annotated libraries */ @Documented @Retention(RetentionPolicy.SOURCE) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PACKAGE}) +@Repeatable(AnnotatedFor.List.class) public @interface AnnotatedFor { /** * Returns the type systems for which the class has been annotated. Legal arguments are any @@ -50,4 +61,22 @@ * @return whether this annotation should be inherited by subpackages */ boolean applyToSubpackages() default true; + + /** + * A wrapper annotation that makes the {@link AnnotatedFor} annotation repeatable. + * + *

      Programmers generally do not need to write this. It is created by Java when a programmer + * writes more than one {@link AnnotatedFor} annotation at the same location. + */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PACKAGE}) + public static @interface List { + /** + * Returns the repeatable annotations. + * + * @return the repeatable annotations + */ + AnnotatedFor[] value(); + } } From 74ab5b407150811a8d8e9df9c84e9eec0a546ab9 Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Wed, 9 Sep 2026 21:34:49 -0400 Subject: [PATCH 51/82] Fix import order and stray blank line from #139 (#143) Co-authored-by: Claude Sonnet 5 --- .../classes/java/util/InvalidPropertiesFormatException.java | 5 +++-- .../share/classes/java/util/ServiceConfigurationError.java | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/util/InvalidPropertiesFormatException.java b/src/java.base/share/classes/java/util/InvalidPropertiesFormatException.java index 21814052fd5..cea97b53750 100644 --- a/src/java.base/share/classes/java/util/InvalidPropertiesFormatException.java +++ b/src/java.base/share/classes/java/util/InvalidPropertiesFormatException.java @@ -25,11 +25,12 @@ package java.util; -import java.io.NotSerializableException; -import java.io.IOException; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.framework.qual.AnnotatedFor; +import java.io.NotSerializableException; +import java.io.IOException; + /** * Thrown to indicate that an operation could not complete because * the input did not conform to the appropriate XML document type diff --git a/src/java.base/share/classes/java/util/ServiceConfigurationError.java b/src/java.base/share/classes/java/util/ServiceConfigurationError.java index 4144fcded18..bdd012e9723 100644 --- a/src/java.base/share/classes/java/util/ServiceConfigurationError.java +++ b/src/java.base/share/classes/java/util/ServiceConfigurationError.java @@ -28,7 +28,6 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.framework.qual.AnnotatedFor; - /** * Error thrown when something goes wrong while locating, loading, or * instantiating a service provider. From 0af1a5ad1f994431fc6e08540000c4ae1ab13153 Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Mon, 14 Sep 2026 14:15:29 -0400 Subject: [PATCH 52/82] Introduce `@UnannotatedFor` (#144) --- .../framework/qual/UnannotatedFor.java | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/java.base/share/classes/org/checkerframework/framework/qual/UnannotatedFor.java diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/UnannotatedFor.java b/src/java.base/share/classes/org/checkerframework/framework/qual/UnannotatedFor.java new file mode 100644 index 00000000000..43ce4206781 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/UnannotatedFor.java @@ -0,0 +1,86 @@ +package org.checkerframework.framework.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates that this package, class, method, or constructor has not been annotated for the given + * type system, even though an enclosing element is annotated for it. For example, if a package is + * {@code @AnnotatedFor("nullness")} but one of its classes has not been annotated with + * {@code @Nullable} and friends, mark that class {@code @UnannotatedFor("nullness")}. The argument + * to {@code UnannotatedFor} is not an annotation name, but a checker name. + * + *

      This annotation has no effect unless the {@code + * -AuseConservativeDefaultsForUncheckedCode=source} or the {@code -AonlyAnnotatedFor} command-line + * argument is supplied. It only subtracts from the scope of an enclosing {@link AnnotatedFor}: an + * element in its scope is treated as if no enclosing {@code @AnnotatedFor} were present, so its + * warnings are suppressed, and under {@code -AuseConservativeDefaultsForUncheckedCode=source} it is + * also defaulted using conservative defaults. ({@code -AonlyAnnotatedFor} suppresses warnings + * without changing defaults, the same as for {@link AnnotatedFor}.) An {@code @AnnotatedFor} on a + * nested element takes effect again for that element. Writing both an {@code @AnnotatedFor} and an + * {@code @UnannotatedFor} that name the same checker on one declaration is a warning ({@code + * conflicting.annotatedfor}), because the two contradict each other; if that warning is suppressed, + * the {@code @AnnotatedFor} wins, since {@code @UnannotatedFor} only subtracts from an + * enclosing scope. + * + *

      An {@code @UnannotatedFor} on a package also applies to subpackages, unless the {@code + * applyToSubpackages} field is set to false. The innermost package annotation wins: an + * {@code @UnannotatedFor} on a package excludes its subpackages from an {@code @AnnotatedFor} on an + * enclosing package, and vice versa. + * + *

      You may write multiple {@code @UnannotatedFor} annotations at the same location, for example + * to give two type systems different {@code applyToSubpackages} settings on one package: + * + *

      + *   {@literal @}UnannotatedFor(value = "nullness", applyToSubpackages = false)
      + *   {@literal @}UnannotatedFor(value = "index", applyToSubpackages = true)
      + *   package mypackage;
      + * 
      + * + * @checker_framework.manual #compiling-libraries Compiling partially-annotated libraries + */ +@Documented +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PACKAGE}) +@Repeatable(UnannotatedFor.List.class) +public @interface UnannotatedFor { + /** + * Returns the type systems for which the annotated element has not been annotated. Legal + * arguments are any string that may be passed to the {@code -processor} command-line argument: + * the fully-qualified class name for the checker, or a shorthand for built-in checkers. Using + * the annotation with no arguments, as in {@code @UnannotatedFor({})}, has no effect. + * + * @return the type systems for which the annotated element has not been annotated + * @checker_framework.manual #shorthand-for-checkers Short names for built-in checkers + */ + String[] value(); + + /** + * When used on a package, whether this annotation should also apply to subpackages. + * + * @return whether this annotation should be inherited by subpackages + */ + boolean applyToSubpackages() default true; + + /** + * A wrapper annotation that makes the {@link UnannotatedFor} annotation repeatable. + * + *

      Programmers generally do not need to write this. It is created by Java when a programmer + * writes more than one {@link UnannotatedFor} annotation at the same location. + */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PACKAGE}) + public static @interface List { + /** + * Returns the repeatable annotations. + * + * @return the repeatable annotations + */ + UnannotatedFor[] value(); + } +} From ca03a925d8fad40ec2f23bed7b799872b410145a Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Tue, 15 Sep 2026 11:19:51 -0400 Subject: [PATCH 53/82] `@AnnotatedFor` and `@UnannotatedFor` runtime retention (#146) Co-authored-by: Alex Cook Co-authored-by: Claude Opus 5 Co-authored-by: Werner Dietl --- .../org/checkerframework/framework/qual/AnnotatedFor.java | 6 ++++-- .../checkerframework/framework/qual/UnannotatedFor.java | 7 +++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/AnnotatedFor.java b/src/java.base/share/classes/org/checkerframework/framework/qual/AnnotatedFor.java index c10c682b125..f7e5e3650c2 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/AnnotatedFor.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/AnnotatedFor.java @@ -24,6 +24,8 @@ * warnings. However, a class with a relevant {@code @AnnotatedFor} annotation is always defaulted * normally (typically using the CLIMB-to-top rule), and typechecking warnings are issued. * + *

      This annotation is stored in class files and is available via reflection at run time. + * *

      An {@code @AnnotatedFor} on a package also applies to subpackages, unless the {@code * applyToSubpackages} field is set to false. Setting it to false does not block an applicable * {@code @AnnotatedFor} on an enclosing package. @@ -40,7 +42,7 @@ * @checker_framework.manual #compiling-libraries Compiling partially-annotated libraries */ @Documented -@Retention(RetentionPolicy.SOURCE) +@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PACKAGE}) @Repeatable(AnnotatedFor.List.class) public @interface AnnotatedFor { @@ -69,7 +71,7 @@ * writes more than one {@link AnnotatedFor} annotation at the same location. */ @Documented - @Retention(RetentionPolicy.SOURCE) + @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PACKAGE}) public static @interface List { /** diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/UnannotatedFor.java b/src/java.base/share/classes/org/checkerframework/framework/qual/UnannotatedFor.java index 43ce4206781..5280ce8d266 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/UnannotatedFor.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/UnannotatedFor.java @@ -27,6 +27,9 @@ * the {@code @AnnotatedFor} wins, since {@code @UnannotatedFor} only subtracts from an * enclosing scope. * + *

      Like {@link AnnotatedFor}, this annotation is stored in class files and is available via + * reflection at run time. + * *

      An {@code @UnannotatedFor} on a package also applies to subpackages, unless the {@code * applyToSubpackages} field is set to false. The innermost package annotation wins: an * {@code @UnannotatedFor} on a package excludes its subpackages from an {@code @AnnotatedFor} on an @@ -44,7 +47,7 @@ * @checker_framework.manual #compiling-libraries Compiling partially-annotated libraries */ @Documented -@Retention(RetentionPolicy.SOURCE) +@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PACKAGE}) @Repeatable(UnannotatedFor.List.class) public @interface UnannotatedFor { @@ -73,7 +76,7 @@ * writes more than one {@link UnannotatedFor} annotation at the same location. */ @Documented - @Retention(RetentionPolicy.SOURCE) + @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PACKAGE}) public static @interface List { /** From 92a35a0cbaf7508458f1ef82bc2e327150978c1d Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Tue, 15 Sep 2026 14:33:50 -0400 Subject: [PATCH 54/82] Document `SOURCE` retention and add missing `@Retention` to `PolyInitializedFields` (#147) --- .../common/initializedfields/qual/PolyInitializedFields.java | 5 +++++ .../common/value/qual/IntRangeFromGTENegativeOne.java | 2 ++ .../common/value/qual/IntRangeFromNonNegative.java | 2 ++ .../common/value/qual/IntRangeFromPositive.java | 2 ++ .../org/checkerframework/framework/qual/CFComment.java | 4 ++++ 5 files changed, 15 insertions(+) diff --git a/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/PolyInitializedFields.java b/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/PolyInitializedFields.java index 6fc0b75789e..7b8788cbe89 100644 --- a/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/PolyInitializedFields.java +++ b/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/PolyInitializedFields.java @@ -2,7 +2,10 @@ import org.checkerframework.framework.qual.PolymorphicQualifier; +import java.lang.annotation.Documented; import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** @@ -10,6 +13,8 @@ * * @checker_framework.manual #initialized-fields-checker Initialized Fields Checker */ +@Documented +@Retention(RetentionPolicy.RUNTIME) @PolymorphicQualifier(InitializedFields.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) public @interface PolyInitializedFields {} diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromGTENegativeOne.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromGTENegativeOne.java index 231f9116087..c1cbd3a1673 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromGTENegativeOne.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromGTENegativeOne.java @@ -28,6 +28,8 @@ * @checker_framework.manual #constant-value-checker Constant Value Checker */ @Documented +// Do not store in class file: this is only an internal alias of an Index Checker qualifier, such as +// @GTENegativeOne, which is stored instead. @Retention(RetentionPolicy.SOURCE) @Target({}) @SubtypeOf(UnknownVal.class) diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromNonNegative.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromNonNegative.java index 0d39d1bf601..ecce8296e88 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromNonNegative.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromNonNegative.java @@ -28,6 +28,8 @@ * @checker_framework.manual #constant-value-checker Constant Value Checker */ @Documented +// Do not store in class file: this is only an internal alias of an Index Checker qualifier, such as +// @NonNegative, which is stored instead. @Retention(RetentionPolicy.SOURCE) @Target({}) @SubtypeOf(UnknownVal.class) diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromPositive.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromPositive.java index 38fc9f88a18..f1cfc6084f3 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromPositive.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/IntRangeFromPositive.java @@ -28,6 +28,8 @@ * @checker_framework.manual #constant-value-checker Constant Value Checker */ @Documented +// Do not store in class file: this is only an internal alias of an Index Checker qualifier, such as +// @Positive, which is stored instead. @Retention(RetentionPolicy.SOURCE) @Target({}) @SubtypeOf(UnknownVal.class) diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/CFComment.java b/src/java.base/share/classes/org/checkerframework/framework/qual/CFComment.java index c6ed6140cf9..3429d5f8b15 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/CFComment.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/CFComment.java @@ -25,6 +25,10 @@ * to which the comment applies (e.g., local variable rather than method, and method rather than * class). * + *

      This annotation has source retention: its comments are for people who read and maintain the + * source code, and the Checker Framework does not interpret them, so they are not stored in class + * files. + * * @checker_framework.manual #library-tips-dont-change-the-code Don't change the code */ @Documented From f5b4023666177830a9849da7eb3c173c7c2de2f5 Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Wed, 16 Sep 2026 22:23:26 -0400 Subject: [PATCH 55/82] Clarify roles of `@Deterministic`, `@Pure`, and `@SideEffectFree` annotations (#148) Co-authored-by: Claude Opus 5 Co-authored-by: Werner Dietl --- .../dataflow/qual/Deterministic.java | 30 +++++++++++++++++-- .../checkerframework/dataflow/qual/Pure.java | 7 +++++ .../dataflow/qual/SideEffectFree.java | 5 +++- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/org/checkerframework/dataflow/qual/Deterministic.java b/src/java.base/share/classes/org/checkerframework/dataflow/qual/Deterministic.java index c56484f0dd6..b31734493bc 100644 --- a/src/java.base/share/classes/org/checkerframework/dataflow/qual/Deterministic.java +++ b/src/java.base/share/classes/org/checkerframework/dataflow/qual/Deterministic.java @@ -18,9 +18,10 @@ * *

      This annotation is important to pluggable type-checking because, after a call to a * {@code @Deterministic} method, flow-sensitive type refinement can assume that anything learned - * about the first invocation is true about subsequent invocations (so long as no - * non-{@code @}{@link SideEffectFree} method call intervenes). For example, the following code - * never suffers a null pointer exception, so the Nullness Checker need not issue a warning: + * about the first invocation is true about subsequent invocations, so long as the environment does + * not change in between. For example, if {@code myDeterministicMethod} is also {@link + * SideEffectFree}, the following code never suffers a null pointer exception, so the Nullness + * Checker need not issue a warning: * *

      {@code
        * if (x.myDeterministicMethod() != null) {
      @@ -28,6 +29,29 @@
        * }
        * }
      * + *

      The environment can change between the two invocations because of an intervening call to a + * non-{@code @}{@link SideEffectFree} method, but also because of the first invocation itself: + * determinism does not prevent a method from modifying the heap. For example, the following method + * is deterministic according to the definition above, but it is not side-effect-free, and in the + * code above its second invocation returns {@code null} (assuming {@code this.f} was initially + * non-null): + * + *

      {@code
      + * Object myDeterministicMethod() {
      + *   Object o = this.f;
      + *   this.f = null;
      + *   return o;
      + * }
      + * }
      + * + *

      Nevertheless, the Checker Framework currently assumes that repeated invocations of any + * {@code @Deterministic} method return the same value, even if the method is not + * {@code @SideEffectFree}. This assumption is justified only when the annotation is checked, + * because the checking rules below forbid side effects in a {@code @Deterministic} method, and + * checking is disabled by default. Therefore, do not write {@code @Deterministic} on a method that + * has side effects, such as the one above. To state that a method is both deterministic and + * side-effect-free, write {@link Pure}. + * *

      Note that {@code @Deterministic} guarantees that the result is identical according to {@code * ==}, not just equal according to {@code equals()}. This means that writing * {@code @Deterministic} on a method that returns a reference (including a String) is often diff --git a/src/java.base/share/classes/org/checkerframework/dataflow/qual/Pure.java b/src/java.base/share/classes/org/checkerframework/dataflow/qual/Pure.java index 1b57e655fd9..6c7ddbdc26b 100644 --- a/src/java.base/share/classes/org/checkerframework/dataflow/qual/Pure.java +++ b/src/java.base/share/classes/org/checkerframework/dataflow/qual/Pure.java @@ -11,6 +11,13 @@ * Deterministic}. The more important of these, when performing pluggable type-checking, is usually * {@link SideEffectFree}. * + *

      For pluggable type-checking, {@link SideEffectFree} lets flow-sensitive type refinement keep + * facts about the heap across a call to the method, and {@link Deterministic} lets it assume that a + * later invocation of the method, with the same arguments and in the same environment, returns the + * same value as an earlier one. Because a deterministic method that is not side-effect-free can + * change the environment itself, both are needed for a fact learned about the result of one + * invocation to hold for the result of the next; see {@link Deterministic} for an example. + * *

      For a discussion of the meaning of {@code Pure} on a constructor, see the documentation of * {@link Deterministic}. * diff --git a/src/java.base/share/classes/org/checkerframework/dataflow/qual/SideEffectFree.java b/src/java.base/share/classes/org/checkerframework/dataflow/qual/SideEffectFree.java index da33d80443e..00d1fab83a5 100644 --- a/src/java.base/share/classes/org/checkerframework/dataflow/qual/SideEffectFree.java +++ b/src/java.base/share/classes/org/checkerframework/dataflow/qual/SideEffectFree.java @@ -22,7 +22,10 @@ * modified, which annuls the effect of flow-sensitive type refinement and prevents the pluggable * type-checker from making conclusions that are obvious to a programmer. * - *

      Also see {@link Pure}, which means both side-effect-free and {@link Deterministic}. + *

      Being side-effect-free does not imply that two invocations of the method return the same + * value. Also see {@link Pure}, which means both side-effect-free and {@link Deterministic}, and + * which lets a pluggable type-checker assume that repeated invocations with the same arguments + * return the same value, so long as no other side effect intervenes. * *

      Analysis: The Checker Framework performs a conservative analysis to verify a * {@code @SideEffectFree} annotation. The Checker Framework issues a warning if the method uses any From ed063b68ebc6b24c4ca10e1f179dd3363c44be29 Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Wed, 16 Sep 2026 23:05:06 -0400 Subject: [PATCH 56/82] Update CI JDK versions, fail on test failures, and configure Renovate (#149) --- .github/renovate.json | 20 ++++++++++++++++++++ .github/workflows/ci.yml | 34 +++++++++++++++++----------------- 2 files changed, 37 insertions(+), 17 deletions(-) create mode 100644 .github/renovate.json diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 00000000000..68de9706e58 --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended", + ":automergeDisabled", + ":automergeRequireAllStatusChecks", + "schedule:nonOfficeHours" + ], + "minimumReleaseAge": "7 days", + "prConcurrentLimit": 5, + "timezone": "America/Los_Angeles", + "packageRules": [ + { + "description": "Group non-major GitHub Actions updates", + "matchManagers": ["github-actions"], + "matchUpdateTypes": ["minor", "patch", "pin", "digest"], + "groupName": "GitHub Actions non-major updates" + } + ] +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6de18c92f96..e174b8dff28 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,10 +22,10 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up JDK 17 - uses: actions/setup-java@v4 + uses: actions/setup-java@v6.0.0 with: java-version: 17 - distribution: 'temurin' + distribution: 'zulu' - name: Install dependencies run: | sudo apt-get update @@ -47,34 +47,34 @@ jobs: permissions: contents: read strategy: + fail-fast: false matrix: script: ['cftests-junit', 'cftests-nonjunit'] - java_version: ['8', '11', '17', '21', '24', '25-ea'] - continue-on-error: true + java_version: ['8', '11', '17', '21', '25', '27'] env: JAVA_VERSION: ${{ matrix.java_version }} steps: - uses: actions/checkout@v4 - name: Set up JDK 21 for Gradle to run on - uses: actions/setup-java@v4 + uses: actions/setup-java@v6.0.0 with: # Install JDK 21 first, to make it available to Gradle using `gradle.properties` below. java-version: '21' - distribution: 'temurin' + distribution: 'zulu' - name: Set up JDK ${{ matrix.java_version }} - uses: actions/setup-java@v4 + uses: actions/setup-java@v6.0.0 with: java-version: ${{ matrix.java_version }} - distribution: 'temurin' + distribution: 'zulu' - name: Inject JAVA_HOME_21_64 into `gradle.properties` to always use JDK 21 for Gradle run: mkdir ~/.gradle && echo "org.gradle.java.home=$JAVA_HOME_21_X64" >> ~/.gradle/gradle.properties - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4.3.1 + uses: gradle/actions/setup-gradle@v6.3.0 - name: Setup Bazel - uses: bazel-contrib/setup-bazel@0.9.0 + uses: bazel-contrib/setup-bazel@0.19.0 if: ${{ matrix.script == 'cftests-nonjunit' }} with: bazelisk-cache: true @@ -110,13 +110,13 @@ jobs: - uses: actions/checkout@v4 - name: Set up JDK ${{ matrix.java_version }} - uses: actions/setup-java@v4 + uses: actions/setup-java@v6.0.0 with: java-version: ${{ matrix.java_version }} - distribution: 'temurin' + distribution: 'zulu' - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4.1.0 + uses: gradle/actions/setup-gradle@v6.3.0 - name: Clone plume-scripts run: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth 1 -q https://github.com/eisop-plume-lib/plume-scripts.git @@ -141,15 +141,15 @@ jobs: env: JAVA_VERSION: ${{ matrix.java_version }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up JDK ${{ matrix.java_version }} - uses: actions/setup-java@v4 + uses: actions/setup-java@v6.0.0 with: java-version: ${{ matrix.java_version }} - distribution: 'temurin' + distribution: 'zulu' - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4.1.0 + uses: gradle/actions/setup-gradle@v6.3.0 - name: Clone plume-scripts run: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth 1 -q https://github.com/eisop-plume-lib/plume-scripts.git From 9eaa3b20c4fea350ee09c45ef16b3c9907e5fb67 Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Thu, 24 Sep 2026 21:45:55 -0400 Subject: [PATCH 57/82] Introduce `@ProgrammaticDefaultLocations` for programmatic defaults (#150) --- .../qual/ProgrammaticDefaultLocations.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/java.base/share/classes/org/checkerframework/framework/qual/ProgrammaticDefaultLocations.java diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/ProgrammaticDefaultLocations.java b/src/java.base/share/classes/org/checkerframework/framework/qual/ProgrammaticDefaultLocations.java new file mode 100644 index 00000000000..6b7df111f5a --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/ProgrammaticDefaultLocations.java @@ -0,0 +1,36 @@ +package org.checkerframework.framework.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * A meta-annotation that specifies the type-use locations where a type qualifier is permitted to be + * used as a programmatic default (e.g. by {@link + * org.checkerframework.framework.util.defaults.QualifierDefaults#addCheckedCodeDefault}, {@link + * org.checkerframework.framework.util.defaults.QualifierDefaults#addUncheckedCodeDefault}, or + * {@link org.checkerframework.framework.util.defaults.QualifierDefaults#addElementDefault}), even + * if the qualifier's {@link TargetLocations} meta-annotation prohibits explicit use by programmers + * at those locations. + * + *

      If used as a marker annotation without arguments (the default), the qualifier is permitted as + * a programmatic default at all type-use locations ({@link TypeUseLocation#ALL}). + * + *

      If a qualifier has no {@code @ProgrammaticDefaultLocations} annotation, top and bottom + * qualifiers in a qualifier hierarchy are permitted as programmatic defaults at all locations by + * default. Other qualifiers are permitted only at the locations allowed by their {@link + * TargetLocations} meta-annotation (or all locations if {@link TargetLocations} is also omitted). + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.ANNOTATION_TYPE) +public @interface ProgrammaticDefaultLocations { + /** + * Type-use locations at which the qualifier is permitted as a programmatic default. + * + * @return type-use locations + */ + TypeUseLocation[] value() default {TypeUseLocation.ALL}; +} From 2b53d9059b68fa246aff7f37748e9332b707fb3d Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Sun, 27 Sep 2026 09:44:38 -0400 Subject: [PATCH 58/82] Update StubFiles Javadoc for inheritance and compound checkers (#151) --- .../org/checkerframework/framework/qual/StubFiles.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/StubFiles.java b/src/java.base/share/classes/org/checkerframework/framework/qual/StubFiles.java index 64dbeff0700..18f3309d3b2 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/StubFiles.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/StubFiles.java @@ -11,9 +11,9 @@ * addition to {@code jdk.astub}. This allows larger compound checkers to separate the annotations * into multiple files, or to provide annotations for non-JDK classes. * - *

      This annotation is not inherited. That means that if a checker with this annotation is - * subclassed, then this annotation must be copied to the subclass and the stub file must also be - * copied to the directory that contains the subclass. + *

      A checker inherits the stub files of the nearest superclass that declares this annotation, + * unless it declares its own {@code @StubFiles} annotation. Furthermore, stub files are shared + * bidirectionally between compound checkers and their subcheckers. * * @checker_framework.manual #creating-a-checker-annotated-jdk Annotated JDK */ @@ -24,6 +24,8 @@ /** * Stub file names. These are basenames: they include the extension (usually ".astub"), but no * directory component. + * + * @return the stub file names */ String[] value(); } From c95a4729258071c1b9dd2bb8bc5baccef78ead9b Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Sun, 27 Sep 2026 13:59:50 -0400 Subject: [PATCH 59/82] Update RelevantJavaTypes Javadoc for superclass inheritance (#152) --- .../checkerframework/framework/qual/RelevantJavaTypes.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/RelevantJavaTypes.java b/src/java.base/share/classes/org/checkerframework/framework/qual/RelevantJavaTypes.java index ce53d197aa5..656fd6d5a18 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/RelevantJavaTypes.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/RelevantJavaTypes.java @@ -13,6 +13,12 @@ * their subtypes. If a checker is not annotated with this annotation, then the checker's qualifiers * may appear on any type. * + *

      In order for this annotation to have an effect, it must be placed on the declaration of a + * class that extends {@code org.checkerframework.framework.source.SourceChecker}. {@code + * org.checkerframework.framework.source.SourceChecker#getRelevantJavaTypes} collects these + * annotations from the checker's class hierarchy, so a subclass inherits and combines the relevant + * Java types of its superclasses. + * *

      This restriction is coarse-grained in that it applies to all type annotations for a given * checker. To have different restrictions for different Java types, override {@code * org.checkerframework.common.basetype.BaseTypeVisitor#visitAnnotatedType(List, Tree)}. From 618afed9cecb5fb5f6b488150c868ffc82046b71 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Wed, 6 Aug 2025 13:14:18 -0700 Subject: [PATCH 60/82] Refresh qualifier definitions --- src/java.base/share/classes/module-info.java | 2 +- .../calledmethods/qual/EnsuresCalledMethods.java | 2 +- .../calledmethods/qual/EnsuresCalledMethodsIf.java | 2 +- .../qual/EnsuresCalledMethodsOnException.java | 6 +++--- .../i18nformatter/qual/I18nConversionCategory.java | 2 +- .../checker/index/qual/EnsuresLTLengthOf.java | 6 ++++-- .../checker/index/qual/EnsuresLTLengthOfIf.java | 2 +- .../checker/lock/qual/EnsuresLockHeld.java | 2 +- .../checker/lock/qual/EnsuresLockHeldIf.java | 2 +- .../checker/mustcall/qual/CreatesMustCallFor.java | 2 +- .../qual/EnsuresInitializedFields.java | 2 +- .../common/value/qual/EnsuresMinLenIf.java | 2 +- .../checkerframework/dataflow/qual/AssertMethod.java | 10 +++++----- .../framework/qual/DefaultQualifier.java | 2 +- .../framework/qual/EnsuresQualifier.java | 2 +- .../framework/qual/EnsuresQualifierIf.java | 2 +- 16 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index 9f87b6e5391..2fb5a09bf26 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -82,8 +82,8 @@ exports org.checkerframework.checker.fenum.qual; exports org.checkerframework.checker.formatter.qual; exports org.checkerframework.checker.guieffect.qual; - exports org.checkerframework.checker.i18n.qual; exports org.checkerframework.checker.i18nformatter.qual; + exports org.checkerframework.checker.i18n.qual; exports org.checkerframework.checker.index.qual; exports org.checkerframework.checker.initialization.qual; exports org.checkerframework.checker.interning.qual; diff --git a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethods.java b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethods.java index d3728957fd0..ef86d39da3a 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethods.java +++ b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethods.java @@ -78,7 +78,7 @@ @PostconditionAnnotation(qualifier = CalledMethods.class) public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsIf.java b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsIf.java index 62177670599..12c36c1319c 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsIf.java +++ b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsIf.java @@ -65,7 +65,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsOnException.java b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsOnException.java index c561433cd86..b8b991727e4 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsOnException.java +++ b/src/java.base/share/classes/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsOnException.java @@ -23,8 +23,8 @@ * public void callM(T t) { ... } * * - *

      The callM method promises to always call {@code t.m()} before throwing any kind - * of {@link Exception}. + *

      The {@code callM} method promises to always call {@code t.m()} before throwing any kind of + * {@link Exception}. * *

      Note that {@code EnsuresCalledMethodsOnException} only describes behavior for {@link * Exception} (and by extension {@link RuntimeException}, {@link NullPointerException}, etc.) but @@ -89,7 +89,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/i18nformatter/qual/I18nConversionCategory.java b/src/java.base/share/classes/org/checkerframework/checker/i18nformatter/qual/I18nConversionCategory.java index 8b40222226e..642ac30d5f4 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/i18nformatter/qual/I18nConversionCategory.java +++ b/src/java.base/share/classes/org/checkerframework/checker/i18nformatter/qual/I18nConversionCategory.java @@ -94,7 +94,7 @@ private static Set arrayToSet(E[] a) { } /** - * Return true if a is a subset of b. + * Returns true if a is a subset of b. * * @return true if a is a subset of b */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/EnsuresLTLengthOf.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/EnsuresLTLengthOf.java index abc186b8321..526980b78e2 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/EnsuresLTLengthOf.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/EnsuresLTLengthOf.java @@ -22,7 +22,9 @@ * {@code @EnsuresLTLengthOf(value = "end", targetValue = "array", offset = "#1 - 1") * public void shiftIndex(@NonNegative int x) { * int newEnd = end - x; - * if (newEnd < 0) throw new RuntimeException(); + * if (newEnd < 0) { + * throw new RuntimeException(); + * } * end = newEnd; * } * } @@ -98,7 +100,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/EnsuresLTLengthOfIf.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/EnsuresLTLengthOfIf.java index b0630a0e2f3..1eb982bb272 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/EnsuresLTLengthOfIf.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/EnsuresLTLengthOfIf.java @@ -108,7 +108,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeld.java b/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeld.java index 8b76dfd8562..76acd828015 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeld.java +++ b/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeld.java @@ -48,7 +48,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeldIf.java b/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeldIf.java index 2e4ca1c556a..fc11803def0 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeldIf.java +++ b/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeldIf.java @@ -59,7 +59,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/CreatesMustCallFor.java b/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/CreatesMustCallFor.java index b1c71880a61..be2690f41dd 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/CreatesMustCallFor.java +++ b/src/java.base/share/classes/org/checkerframework/checker/mustcall/qual/CreatesMustCallFor.java @@ -104,7 +104,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/EnsuresInitializedFields.java b/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/EnsuresInitializedFields.java index 264e931be79..85d7b3680c7 100644 --- a/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/EnsuresInitializedFields.java +++ b/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/EnsuresInitializedFields.java @@ -51,7 +51,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/EnsuresMinLenIf.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/EnsuresMinLenIf.java index 298b1ba3edd..2b93ba81649 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/EnsuresMinLenIf.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/EnsuresMinLenIf.java @@ -66,7 +66,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/dataflow/qual/AssertMethod.java b/src/java.base/share/classes/org/checkerframework/dataflow/qual/AssertMethod.java index 5622d6de0f2..6658f1b929d 100644 --- a/src/java.base/share/classes/org/checkerframework/dataflow/qual/AssertMethod.java +++ b/src/java.base/share/classes/org/checkerframework/dataflow/qual/AssertMethod.java @@ -14,9 +14,9 @@ *

      The annotation enables flow-sensitive type refinement to be more precise. For example, if * {@code Assertions.assertTrue} is annotated as follows: * - *

      @AssertMethod(value = AssertionFailedError.class)
      + * 
      {@code @AssertMethod(value = AssertionFailedError.class)
        * public static void assertFalse(boolean condition);
      - * 
      + * }
      * * Then, in the code below, the Optional Checker can determine that {@code optional} has a value and * the call to {@code Optional#get} will not throw an exception. @@ -53,15 +53,15 @@ int parameter() default 1; /** - * Returns whether this method asserts that the boolean expression is false. + * Returns true if this method asserts that the boolean expression is false. * *

      For example, JUnit's Assertions.assertFalse(...) * throws an exception if the first argument is false. So it is annotated as follows: * - *

      @AssertMethod(value = AssertionFailedError.class, isAssertFalse = true)
      +     * 
      {@code @AssertMethod(value = AssertionFailedError.class, isAssertFalse = true)
            * public static void assertFalse(boolean condition);
      -     * 
      + * }
      * * @return the value for {@link #parameter} on which the method throws an exception */ diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultQualifier.java b/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultQualifier.java index 936cd8644ce..f791c1762b9 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultQualifier.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultQualifier.java @@ -92,7 +92,7 @@ }) public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifier.java b/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifier.java index f6d4232f977..bce3e983009 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifier.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifier.java @@ -65,7 +65,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifierIf.java b/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifierIf.java index 4d502b6d38d..b44fff876e3 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifierIf.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifierIf.java @@ -77,7 +77,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ From 5d9431d7e4ea55d32a5e5c2679681b64a38abc8b Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 12 Aug 2025 08:00:23 -0700 Subject: [PATCH 61/82] `@Shrinkable` annotations Resolved for EISOP: the existing @Nullable return types of the queue poll methods are kept, @SideEffectsOnly is not used because the EISOP Checker Framework does not have it, and the checker-qual.jar that this repository no longer has stays deleted. Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01GW8C4XvQcY7RQkVAqStDB6 --- README.md | 4 +- .../share/classes/java/lang/Iterable.java | 3 +- .../classes/java/util/AbstractCollection.java | 12 ++-- .../share/classes/java/util/AbstractList.java | 17 +++--- .../classes/java/util/AbstractQueue.java | 5 +- .../java/util/AbstractSequentialList.java | 9 ++- .../share/classes/java/util/ArrayDeque.java | 34 +++++------ .../share/classes/java/util/ArrayList.java | 26 +++++---- .../share/classes/java/util/Collection.java | 14 +++-- .../share/classes/java/util/Collections.java | 25 ++++---- .../share/classes/java/util/Deque.java | 29 +++++----- .../share/classes/java/util/HashSet.java | 3 +- .../share/classes/java/util/Iterator.java | 3 +- .../share/classes/java/util/JumboEnumSet.java | 4 +- .../share/classes/java/util/LinkedList.java | 30 +++++----- .../share/classes/java/util/List.java | 20 ++++--- .../share/classes/java/util/NavigableSet.java | 4 +- .../classes/java/util/PriorityQueue.java | 20 ++++--- .../share/classes/java/util/Queue.java | 5 +- .../classes/java/util/RegularEnumSet.java | 4 +- .../share/classes/java/util/Set.java | 3 +- .../share/classes/java/util/Stack.java | 4 +- .../share/classes/java/util/TreeSet.java | 17 +++--- .../share/classes/java/util/Vector.java | 34 +++++------ .../util/concurrent/ArrayBlockingQueue.java | 25 ++++---- .../java/util/concurrent/BlockingDeque.java | 28 +++++---- .../java/util/concurrent/BlockingQueue.java | 8 ++- .../concurrent/ConcurrentLinkedDeque.java | 35 ++++++------ .../concurrent/ConcurrentLinkedQueue.java | 17 +++--- .../concurrent/ConcurrentSkipListSet.java | 20 ++++--- .../util/concurrent/CopyOnWriteArrayList.java | 27 +++++---- .../util/concurrent/CopyOnWriteArraySet.java | 4 +- .../java/util/concurrent/DelayQueue.java | 20 ++++--- .../util/concurrent/LinkedBlockingDeque.java | 57 ++++++++++--------- .../util/concurrent/LinkedBlockingQueue.java | 25 ++++---- .../util/concurrent/LinkedTransferQueue.java | 31 +++++----- .../concurrent/PriorityBlockingQueue.java | 25 ++++---- .../util/concurrent/SynchronousQueue.java | 23 ++++---- .../checker/index/qual/BottomGrowShrink.java | 20 +++++++ .../checker/index/qual/GrowOnly.java | 21 +++++++ .../checker/index/qual/PolyGrowShrink.java | 20 +++++++ .../checker/index/qual/Shrinkable.java | 20 +++++++ .../index/qual/UncheckedShrinkable.java | 28 +++++++++ .../checker/index/qual/UnshrinkableRef.java | 25 ++++++++ 44 files changed, 512 insertions(+), 296 deletions(-) create mode 100644 src/java.base/share/classes/org/checkerframework/checker/index/qual/BottomGrowShrink.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/index/qual/GrowOnly.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/index/qual/PolyGrowShrink.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/index/qual/Shrinkable.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/index/qual/UncheckedShrinkable.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/index/qual/UnshrinkableRef.java diff --git a/README.md b/README.md index dac75c06d8c..4b960ad8ddd 100644 --- a/README.md +++ b/README.md @@ -133,8 +133,8 @@ jar tf checker-qual-sources.jar | grep '\.java$' | sed 's/\/[^/]*\.java/;/' | se The result of the command will be a list of export lines. Replace the existing export lines present in `src/java.base/share/classes/module-info.java` with the newly-generated list of -exports. If no new packages were added, then there are likely going to be no -changes to the `module-info.java` file. +exports. If no new packages were added, then likely no changes are needed +in the `module-info.java` file. Commit the changes. Do not include the top-level `checker-qual-source.jar` file, but include any new `.java` files in a `qual/` directory. diff --git a/src/java.base/share/classes/java/lang/Iterable.java b/src/java.base/share/classes/java/lang/Iterable.java index 89990f6f8f7..2b0cacbbfbc 100644 --- a/src/java.base/share/classes/java/lang/Iterable.java +++ b/src/java.base/share/classes/java/lang/Iterable.java @@ -24,6 +24,7 @@ */ package java.lang; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.common.aliasing.qual.NonLeaked; import org.checkerframework.framework.qual.AnnotatedFor; @@ -50,7 +51,7 @@ public interface Iterable { * * @return an Iterator. */ - @PolyNonEmpty Iterator iterator(@PolyNonEmpty Iterable this); + @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty Iterable this); /** * Performs the given action for each element of the {@code Iterable} diff --git a/src/java.base/share/classes/java/util/AbstractCollection.java b/src/java.base/share/classes/java/util/AbstractCollection.java index b9f991dab08..67c1797c19d 100644 --- a/src/java.base/share/classes/java/util/AbstractCollection.java +++ b/src/java.base/share/classes/java/util/AbstractCollection.java @@ -26,6 +26,8 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; @@ -92,7 +94,7 @@ protected AbstractCollection() { * @return an iterator over the elements contained in this collection */ @SideEffectFree - public abstract @PolyNonEmpty Iterator iterator(@PolyNonEmpty AbstractCollection this); + public abstract @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty AbstractCollection this); @Pure public abstract @NonNegative int size(@GuardSatisfied AbstractCollection this); @@ -292,7 +294,7 @@ public boolean add(@GuardSatisfied AbstractCollection this, E e) { * @throws ClassCastException {@inheritDoc} * @throws NullPointerException {@inheritDoc} */ - public boolean remove(@GuardSatisfied AbstractCollection this, @GuardSatisfied @UnknownSignedness Object o) { + public boolean remove(@GuardSatisfied @Shrinkable AbstractCollection this, @GuardSatisfied @UnknownSignedness Object o) { Iterator it = iterator(); if (o==null) { while (it.hasNext()) { @@ -385,7 +387,7 @@ public boolean addAll(@GuardSatisfied AbstractCollection this, Collection this, Collection c) { + public boolean removeAll(@GuardSatisfied @Shrinkable AbstractCollection this, Collection c) { Objects.requireNonNull(c); boolean modified = false; Iterator it = iterator(); @@ -420,7 +422,7 @@ public boolean removeAll(@GuardSatisfied AbstractCollection this, Collection< * @see #remove(Object) * @see #contains(Object) */ - public boolean retainAll(@GuardSatisfied AbstractCollection this, Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable AbstractCollection this, Collection c) { Objects.requireNonNull(c); boolean modified = false; Iterator it = iterator(); @@ -449,7 +451,7 @@ public boolean retainAll(@GuardSatisfied AbstractCollection this, Collection< * * @throws UnsupportedOperationException {@inheritDoc} */ - public void clear(@GuardSatisfied AbstractCollection this) { + public void clear(@GuardSatisfied @Shrinkable AbstractCollection this) { Iterator it = iterator(); while (it.hasNext()) { it.next(); diff --git a/src/java.base/share/classes/java/util/AbstractList.java b/src/java.base/share/classes/java/util/AbstractList.java index 8e1def9c98c..b27cb1d74ab 100644 --- a/src/java.base/share/classes/java/util/AbstractList.java +++ b/src/java.base/share/classes/java/util/AbstractList.java @@ -28,10 +28,13 @@ import org.checkerframework.checker.index.qual.GTENegativeOne; import org.checkerframework.checker.index.qual.IndexFor; import org.checkerframework.checker.index.qual.IndexOrHigh; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; @@ -182,7 +185,7 @@ public void add(@GuardSatisfied AbstractList this, @IndexOrHigh({"this"}) int * @throws UnsupportedOperationException {@inheritDoc} * @throws IndexOutOfBoundsException {@inheritDoc} */ - public E remove(@GuardSatisfied AbstractList this, @IndexFor({"this"}) int index) { + public E remove(@GuardSatisfied @Shrinkable AbstractList this, @IndexFor({"this"}) int index) { throw new UnsupportedOperationException(); } @@ -260,7 +263,7 @@ public E remove(@GuardSatisfied AbstractList this, @IndexFor({"this"}) int in * @throws UnsupportedOperationException if the {@code clear} operation * is not supported by this list */ - public void clear(@GuardSatisfied AbstractList this) { + public void clear(@GuardSatisfied @Shrinkable AbstractList this) { removeRange(0, size()); } @@ -317,7 +320,7 @@ public boolean addAll(@GuardSatisfied AbstractList this, @IndexOrHigh({"this" * @return an iterator over the elements in this list in proper sequence */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty AbstractList this) { return new Itr(); } @@ -329,7 +332,7 @@ public Iterator iterator() { * * @see #listIterator(int) */ - public ListIterator listIterator() { + public @PolyGrowShrink @PolyNonEmpty ListIterator listIterator(@PolyGrowShrink @PolyNonEmpty AbstractList this) { return listIterator(0); } @@ -356,7 +359,7 @@ public ListIterator listIterator() { * * @throws IndexOutOfBoundsException {@inheritDoc} */ - public ListIterator listIterator(final @IndexOrHigh({"this"}) int index) { + public @PolyGrowShrink ListIterator listIterator(@PolyGrowShrink AbstractList this, final @IndexOrHigh({"this"}) int index) { rangeCheckForAdd(index); return new ListItr(index); @@ -518,7 +521,7 @@ public void add(E e) { * {@code (fromIndex > toIndex)} */ @SideEffectFree - public List subList(@GuardSatisfied AbstractList this, @IndexOrHigh({"this"}) int fromIndex, @IndexOrHigh({"this"}) int toIndex) { + public @PolyGrowShrink List subList(@GuardSatisfied @PolyGrowShrink AbstractList this, @IndexOrHigh({"this"}) int fromIndex, @IndexOrHigh({"this"}) int toIndex) { subListRangeCheck(fromIndex, toIndex, size()); return (this instanceof RandomAccess ? new RandomAccessSubList<>(this, fromIndex, toIndex) : @@ -618,7 +621,7 @@ public int hashCode(@GuardSatisfied AbstractList this) { * @param fromIndex index of first element to be removed * @param toIndex index after last element to be removed */ - protected void removeRange(@IndexOrHigh({"this"}) int fromIndex, @IndexOrHigh({"this"}) int toIndex) { + protected void removeRange(@GuardSatisfied @Shrinkable AbstractList this, @IndexOrHigh({"this"}) int fromIndex, @IndexOrHigh({"this"}) int toIndex) { ListIterator it = listIterator(fromIndex); for (int i=0, n=toIndex-fromIndex; i this, E e) { * @return the head of this queue * @throws NoSuchElementException if this queue is empty */ - public E remove(@GuardSatisfied @NonEmpty AbstractQueue this) { + public E remove(@GuardSatisfied @NonEmpty @Shrinkable AbstractQueue this) { E x = poll(); if (x != null) return x; @@ -150,7 +151,7 @@ public E element(@GuardSatisfied @NonEmpty AbstractQueue this) { *

      This implementation repeatedly invokes {@link #poll poll} until it * returns {@code null}. */ - public void clear(@GuardSatisfied AbstractQueue this) { + public void clear(@GuardSatisfied @Shrinkable AbstractQueue this) { while (poll() != null) ; } diff --git a/src/java.base/share/classes/java/util/AbstractSequentialList.java b/src/java.base/share/classes/java/util/AbstractSequentialList.java index 0d1a3b37544..054a8a463fe 100644 --- a/src/java.base/share/classes/java/util/AbstractSequentialList.java +++ b/src/java.base/share/classes/java/util/AbstractSequentialList.java @@ -25,7 +25,10 @@ package java.util; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -175,7 +178,7 @@ public void add(@GuardSatisfied AbstractSequentialList this, int index, E ele * @throws UnsupportedOperationException {@inheritDoc} * @throws IndexOutOfBoundsException {@inheritDoc} */ - public E remove(@GuardSatisfied AbstractSequentialList this, int index) { + public E remove(@GuardSatisfied @Shrinkable AbstractSequentialList this, int index) { try { ListIterator e = listIterator(index); E outCast = e.next(); @@ -244,7 +247,7 @@ public boolean addAll(@GuardSatisfied AbstractSequentialList this, int index, * @return an iterator over the elements in this list (in proper sequence) */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty AbstractSequentialList this) { return listIterator(); } @@ -258,5 +261,5 @@ public Iterator iterator() { * sequence) * @throws IndexOutOfBoundsException {@inheritDoc} */ - public abstract ListIterator listIterator(int index); + public abstract @PolyGrowShrink ListIterator listIterator(@PolyGrowShrink AbstractSequentialList this, int index); } diff --git a/src/java.base/share/classes/java/util/ArrayDeque.java b/src/java.base/share/classes/java/util/ArrayDeque.java index 21ed93dd596..74be144a7ed 100644 --- a/src/java.base/share/classes/java/util/ArrayDeque.java +++ b/src/java.base/share/classes/java/util/ArrayDeque.java @@ -35,6 +35,8 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -374,7 +376,7 @@ public boolean offerLast(E e) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeFirst(@GuardSatisfied @NonEmpty ArrayDeque this) { + public E removeFirst(@GuardSatisfied @NonEmpty @Shrinkable ArrayDeque this) { E e = pollFirst(); if (e == null) throw new NoSuchElementException(); @@ -384,14 +386,14 @@ public E removeFirst(@GuardSatisfied @NonEmpty ArrayDeque this) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeLast(@GuardSatisfied @NonEmpty ArrayDeque this) { + public E removeLast(@GuardSatisfied @NonEmpty @Shrinkable ArrayDeque this) { E e = pollLast(); if (e == null) throw new NoSuchElementException(); return e; } - public @Nullable E pollFirst(@GuardSatisfied ArrayDeque this) { + public @Nullable E pollFirst(@GuardSatisfied @Shrinkable ArrayDeque this) { final Object[] es; final int h; E e = elementAt(es = elements, h = head); @@ -402,7 +404,7 @@ public E removeLast(@GuardSatisfied @NonEmpty ArrayDeque this) { return e; } - public @Nullable E pollLast(@GuardSatisfied ArrayDeque this) { + public @Nullable E pollLast(@GuardSatisfied @Shrinkable ArrayDeque this) { final Object[] es; final int t; E e = elementAt(es = elements, t = dec(tail, es.length)); @@ -455,7 +457,7 @@ public E getLast(@GuardSatisfied @NonEmpty ArrayDeque this) { * @param o element to be removed from this deque, if present * @return {@code true} if the deque contained the specified element */ - public boolean removeFirstOccurrence(@GuardSatisfied ArrayDeque this, @Nullable Object o) { + public boolean removeFirstOccurrence(@GuardSatisfied @Shrinkable ArrayDeque this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o != null) { final Object[] es = elements; for (int i = head, end = tail, to = (i <= end) ? end : es.length; @@ -483,7 +485,7 @@ public boolean removeFirstOccurrence(@GuardSatisfied ArrayDeque this, @Nullab * @param o element to be removed from this deque, if present * @return {@code true} if the deque contained the specified element */ - public boolean removeLastOccurrence(@GuardSatisfied ArrayDeque this, @Nullable Object o) { + public boolean removeLastOccurrence(@GuardSatisfied @Shrinkable ArrayDeque this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o != null) { final Object[] es = elements; for (int i = tail, end = head, to = (i >= end) ? end : 0; @@ -540,7 +542,7 @@ public boolean offer(@GuardSatisfied ArrayDeque this, E e) { * @return the head of the queue represented by this deque * @throws NoSuchElementException {@inheritDoc} */ - public E remove(@GuardSatisfied @NonEmpty ArrayDeque this) { + public E remove(@GuardSatisfied @NonEmpty @Shrinkable ArrayDeque this) { return removeFirst(); } @@ -554,7 +556,7 @@ public E remove(@GuardSatisfied @NonEmpty ArrayDeque this) { * @return the head of the queue represented by this deque, or * {@code null} if this deque is empty */ - public @Nullable E poll(@GuardSatisfied ArrayDeque this) { + public @Nullable E poll(@GuardSatisfied @Shrinkable ArrayDeque this) { return pollFirst(); } @@ -611,7 +613,7 @@ public void push(@GuardSatisfied ArrayDeque this, E e) { * of the stack represented by this deque) * @throws NoSuchElementException {@inheritDoc} */ - public E pop(@GuardSatisfied @NonEmpty ArrayDeque this) { + public E pop(@GuardSatisfied @NonEmpty @Shrinkable ArrayDeque this) { return removeFirst(); } @@ -693,11 +695,11 @@ public boolean isEmpty(@GuardSatisfied ArrayDeque this) { * @return an iterator over the elements in this deque */ @SideEffectFree - public @PolyNonEmpty Iterator iterator(@PolyNonEmpty ArrayDeque this) { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty ArrayDeque this) { return new DeqIterator(); } - public @PolyNonEmpty Iterator descendingIterator(@PolyNonEmpty ArrayDeque this) { + public @PolyGrowShrink @PolyNonEmpty Iterator descendingIterator(@PolyGrowShrink @PolyNonEmpty ArrayDeque this) { return new DescendingIterator(); } @@ -925,7 +927,7 @@ public void forEach(Consumer action) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable ArrayDeque this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -933,7 +935,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable ArrayDeque this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -941,7 +943,7 @@ public boolean removeAll(Collection c) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean retainAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable ArrayDeque this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } @@ -1057,7 +1059,7 @@ public boolean contains(@GuardSatisfied ArrayDeque this, @GuardSatisfied @Nul * @param o element to be removed from this deque, if present * @return {@code true} if this deque contained the specified element */ - public boolean remove(@GuardSatisfied ArrayDeque this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@GuardSatisfied @Shrinkable ArrayDeque this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { return removeFirstOccurrence(o); } @@ -1065,7 +1067,7 @@ public boolean remove(@GuardSatisfied ArrayDeque this, @GuardSatisfied @Nulla * Removes all of the elements from this deque. * The deque will be empty after this call returns. */ - public void clear(@GuardSatisfied ArrayDeque this) { + public void clear(@GuardSatisfied @Shrinkable ArrayDeque this) { circularClear(elements, head, tail); head = tail = 0; } diff --git a/src/java.base/share/classes/java/util/ArrayList.java b/src/java.base/share/classes/java/util/ArrayList.java index fd985d80053..73cda910978 100644 --- a/src/java.base/share/classes/java/util/ArrayList.java +++ b/src/java.base/share/classes/java/util/ArrayList.java @@ -27,6 +27,8 @@ import org.checkerframework.checker.index.qual.GTENegativeOne; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -535,7 +537,7 @@ public void add(@GuardSatisfied ArrayList this, @NonNegative int index, E ele * @return the element that was removed from the list * @throws IndexOutOfBoundsException {@inheritDoc} */ - public E remove(@GuardSatisfied ArrayList this, @NonNegative int index) { + public E remove(@GuardSatisfied @Shrinkable ArrayList this, @NonNegative int index) { Objects.checkIndex(index, size); final Object[] es = elementData; @@ -647,7 +649,7 @@ int hashCodeRange(int from, int to) { * @param o element to be removed from this list, if present * @return {@code true} if this list contained the specified element */ - public boolean remove(@GuardSatisfied ArrayList this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@GuardSatisfied @Shrinkable ArrayList this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { final Object[] es = elementData; final int size = this.size; int i = 0; @@ -683,7 +685,7 @@ private void fastRemove(Object[] es, int i) { * Removes all of the elements from this list. The list will * be empty after this call returns. */ - public void clear(@GuardSatisfied ArrayList this) { + public void clear(@GuardSatisfied @Shrinkable ArrayList this) { modCount++; final Object[] es = elementData; for (int to = size, i = size = 0; i < to; i++) @@ -769,7 +771,7 @@ public boolean addAll(@GuardSatisfied ArrayList this, @NonNegative int index, * toIndex > size() || * toIndex < fromIndex}) */ - protected void removeRange(int fromIndex, int toIndex) { + protected void removeRange(@GuardSatisfied @Shrinkable ArrayList this, int fromIndex, int toIndex) { if (fromIndex > toIndex) { throw new IndexOutOfBoundsException( outOfBoundsMsg(fromIndex, toIndex)); @@ -824,7 +826,7 @@ private static String outOfBoundsMsg(int fromIndex, int toIndex) { * or if the specified collection is null * @see Collection#contains(Object) */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable ArrayList this, Collection c) { return batchRemove(c, false, 0, size); } @@ -844,7 +846,7 @@ public boolean removeAll(Collection c) { * or if the specified collection is null * @see Collection#contains(Object) */ - public boolean retainAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable ArrayList this, Collection c) { return batchRemove(c, true, 0, size); } @@ -956,7 +958,7 @@ private void readObject(java.io.ObjectInputStream s) * * @throws IndexOutOfBoundsException {@inheritDoc} */ - public ListIterator listIterator(@NonNegative int index) { + public @PolyGrowShrink ListIterator listIterator(@PolyGrowShrink ArrayList this, @NonNegative int index) { rangeCheckForAdd(index); return new ListItr(index); } @@ -969,7 +971,7 @@ public ListIterator listIterator(@NonNegative int index) { * * @see #listIterator(int) */ - public ListIterator listIterator() { + public @PolyGrowShrink @PolyNonEmpty ListIterator listIterator(@PolyGrowShrink @PolyNonEmpty ArrayList this) { return new ListItr(0); } @@ -981,7 +983,7 @@ public ListIterator listIterator() { * @return an iterator over the elements in this list in proper sequence */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty ArrayList this) { return new Itr(); } @@ -1145,7 +1147,7 @@ public void add(E e) { * @throws IndexOutOfBoundsException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public List subList(@NonNegative int fromIndex, @NonNegative int toIndex) { + public @PolyGrowShrink List subList(@GuardSatisfied @PolyGrowShrink ArrayList this, @NonNegative int fromIndex, @NonNegative int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList<>(this, fromIndex, toIndex); } @@ -1704,7 +1706,7 @@ private static boolean isClear(long[] bits, int i) { * @throws NullPointerException {@inheritDoc} */ @Override - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable ArrayList this, Predicate filter) { return removeIf(filter, 0, size); } @@ -1712,7 +1714,7 @@ public boolean removeIf(Predicate filter) { * Removes all elements satisfying the given predicate, from index * i (inclusive) to index end (exclusive). */ - boolean removeIf(Predicate filter, int i, final int end) { + boolean removeIf(@Shrinkable ArrayList this, Predicate filter, int i, final int end) { Objects.requireNonNull(filter); int expectedModCount = modCount; final Object[] es = elementData; diff --git a/src/java.base/share/classes/java/util/Collection.java b/src/java.base/share/classes/java/util/Collection.java index 9d6df88aa1b..8ea7ca4d9ef 100644 --- a/src/java.base/share/classes/java/util/Collection.java +++ b/src/java.base/share/classes/java/util/Collection.java @@ -26,6 +26,8 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -321,7 +323,7 @@ public interface Collection extends Iterable { * @return an {@code Iterator} over the elements in this collection */ @SideEffectFree - @PolyNonEmpty Iterator iterator(@PolyNonEmpty Collection this); + @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty Collection this); /** * Returns an array containing all of the elements in this collection. @@ -503,7 +505,7 @@ default T[] toArray(IntFunction generator) { * @throws UnsupportedOperationException if the {@code remove} operation * is not supported by this collection */ - boolean remove(@GuardSatisfied Collection this, @UnknownSignedness Object o); + boolean remove(@GuardSatisfied @Shrinkable Collection this, @UnknownSignedness Object o); // Bulk Operations @@ -578,7 +580,7 @@ default T[] toArray(IntFunction generator) { * @see #remove(Object) * @see #contains(Object) */ - boolean removeAll(@GuardSatisfied Collection this, Collection c); + boolean removeAll(@GuardSatisfied @Shrinkable Collection this, Collection c); /** * Removes all of the elements of this collection that satisfy the given @@ -602,7 +604,7 @@ default T[] toArray(IntFunction generator) { * supported. * @since 1.8 */ - default boolean removeIf(Predicate filter) { + default boolean removeIf(@Shrinkable Collection this, Predicate filter) { Objects.requireNonNull(filter); boolean removed = false; final Iterator each = iterator(); @@ -637,7 +639,7 @@ default boolean removeIf(Predicate filter) { * @see #remove(Object) * @see #contains(Object) */ - boolean retainAll(@GuardSatisfied Collection this, Collection c); + boolean retainAll(@GuardSatisfied @Shrinkable Collection this, Collection c); /** * Removes all of the elements from this collection (optional operation). @@ -646,7 +648,7 @@ default boolean removeIf(Predicate filter) { * @throws UnsupportedOperationException if the {@code clear} operation * is not supported by this collection */ - void clear(@GuardSatisfied Collection this); + void clear(@GuardSatisfied @Shrinkable Collection this); // Comparison and hashing diff --git a/src/java.base/share/classes/java/util/Collections.java b/src/java.base/share/classes/java/util/Collections.java index 2221172db9c..9691dcba77e 100644 --- a/src/java.base/share/classes/java/util/Collections.java +++ b/src/java.base/share/classes/java/util/Collections.java @@ -27,6 +27,7 @@ import org.checkerframework.checker.index.qual.GTENegativeOne; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -1049,7 +1050,7 @@ public static boolean replaceAll(List list, @Nullable T oldVal, T newVal) */ @SuppressWarnings("unchecked") @SideEffectFree - public static @PolyNonEmpty Collection unmodifiableCollection(@PolyNonEmpty Collection c) { + public static @PolyGrowShrink @PolyNonEmpty Collection unmodifiableCollection(@PolyGrowShrink @PolyNonEmpty Collection c) { if (c.getClass() == UnmodifiableCollection.class) { return (Collection) c; } @@ -1088,7 +1089,7 @@ static class UnmodifiableCollection implements Collection, Serializable { public String toString() {return c.toString();} @SideEffectFree - public @PolyNonEmpty Iterator iterator(@PolyNonEmpty UnmodifiableCollection this) { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty UnmodifiableCollection this) { return new Iterator() { private final Iterator i = c.iterator(); @@ -1364,7 +1365,7 @@ public NavigableSet tailSet(E fromElement, boolean inclusive) { * @return an unmodifiable view of the specified list. */ @SuppressWarnings("unchecked") - public static @PolyNonEmpty List unmodifiableList(@PolyNonEmpty List list) { + public static @PolyGrowShrink @PolyNonEmpty List unmodifiableList(@PolyGrowShrink @PolyNonEmpty List list) { if (list.getClass() == UnmodifiableList.class || list.getClass() == UnmodifiableRandomAccessList.class) { return (List) list; } @@ -1418,7 +1419,7 @@ public void sort(Comparator c) { throw new UnsupportedOperationException(); } - public @PolyNonEmpty ListIterator listIterator(@PolyNonEmpty UnmodifiableList this) {return listIterator(0);} + public @PolyGrowShrink @PolyNonEmpty ListIterator listIterator(@PolyGrowShrink @PolyNonEmpty UnmodifiableList this) {return listIterator(0);} public ListIterator listIterator(final int index) { return new ListIterator() { @@ -2123,11 +2124,11 @@ public NavigableMap tailMap(K fromKey, boolean inclusive) * @param c the collection to be "wrapped" in a synchronized collection. * @return a synchronized view of the specified collection. */ - public static Collection synchronizedCollection(Collection c) { + public static @PolyGrowShrink @PolyNonEmpty Collection synchronizedCollection(@PolyGrowShrink @PolyNonEmpty Collection c) { return new SynchronizedCollection<>(c); } - static Collection synchronizedCollection(Collection c, Object mutex) { + static @PolyGrowShrink @PolyNonEmpty Collection synchronizedCollection(@PolyGrowShrink @PolyNonEmpty Collection c, Object mutex) { return new SynchronizedCollection<>(c, mutex); } @@ -2539,13 +2540,13 @@ public NavigableSet tailSet(E fromElement, boolean inclusive) { * @param list the list to be "wrapped" in a synchronized list. * @return a synchronized view of the specified list. */ - public static List synchronizedList(List list) { + public static @PolyGrowShrink @PolyNonEmpty List synchronizedList(@PolyGrowShrink @PolyNonEmpty List list) { return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<>(list) : new SynchronizedList<>(list)); } - static List synchronizedList(List list, Object mutex) { + static @PolyGrowShrink @PolyNonEmpty List synchronizedList(@PolyGrowShrink @PolyNonEmpty List list, Object mutex) { return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<>(list, mutex) : new SynchronizedList<>(list, mutex)); @@ -3216,7 +3217,7 @@ public NavigableMap tailMap(K fromKey, boolean inclusive) { * @return a dynamically typesafe view of the specified collection * @since 1.5 */ - public static Collection checkedCollection(Collection c, + public static @PolyGrowShrink @PolyNonEmpty Collection checkedCollection(@PolyGrowShrink @PolyNonEmpty Collection c, Class type) { return new CheckedCollection<>(c, type); } @@ -3385,7 +3386,7 @@ public boolean removeIf(Predicate filter) { * @return a dynamically typesafe view of the specified queue * @since 1.8 */ - public static Queue checkedQueue(Queue queue, Class type) { + public static @PolyGrowShrink @PolyNonEmpty Queue checkedQueue(@PolyGrowShrink @PolyNonEmpty Queue queue, Class type) { return new CheckedQueue<>(queue, type); } @@ -3640,7 +3641,7 @@ public NavigableSet tailSet(E fromElement, boolean inclusive) { * @return a dynamically typesafe view of the specified list * @since 1.5 */ - public static List checkedList(List list, Class type) { + public static @PolyGrowShrink @PolyNonEmpty List checkedList(@PolyGrowShrink @PolyNonEmpty List list, Class type) { return (list instanceof RandomAccess ? new CheckedRandomAccessList<>(list, type) : new CheckedList<>(list, type)); @@ -5982,7 +5983,7 @@ private void readObject(java.io.ObjectInputStream stream) * @return the queue * @since 1.6 */ - public static Queue asLifoQueue(Deque deque) { + public static @PolyGrowShrink @PolyNonEmpty Queue asLifoQueue(@PolyGrowShrink @PolyNonEmpty Deque deque) { return new AsLIFOQueue<>(Objects.requireNonNull(deque)); } diff --git a/src/java.base/share/classes/java/util/Deque.java b/src/java.base/share/classes/java/util/Deque.java index b39965ec69b..03edbbf4885 100644 --- a/src/java.base/share/classes/java/util/Deque.java +++ b/src/java.base/share/classes/java/util/Deque.java @@ -36,10 +36,13 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; @@ -302,7 +305,7 @@ public interface Deque extends Queue { * @return the head of this deque * @throws NoSuchElementException if this deque is empty */ - E removeFirst(@GuardSatisfied @NonEmpty Deque this); + E removeFirst(@GuardSatisfied @NonEmpty @Shrinkable Deque this); /** * Retrieves and removes the last element of this deque. This method @@ -312,7 +315,7 @@ public interface Deque extends Queue { * @return the tail of this deque * @throws NoSuchElementException if this deque is empty */ - E removeLast(@GuardSatisfied @NonEmpty Deque this); + E removeLast(@GuardSatisfied @NonEmpty @Shrinkable Deque this); /** * Retrieves and removes the first element of this deque, @@ -320,7 +323,7 @@ public interface Deque extends Queue { * * @return the head of this deque, or {@code null} if this deque is empty */ - @Nullable E pollFirst(@GuardSatisfied Deque this); + @Nullable E pollFirst(@GuardSatisfied @Shrinkable Deque this); /** * Retrieves and removes the last element of this deque, @@ -328,7 +331,7 @@ public interface Deque extends Queue { * * @return the tail of this deque, or {@code null} if this deque is empty */ - @Nullable E pollLast(@GuardSatisfied Deque this); + @Nullable E pollLast(@GuardSatisfied @Shrinkable Deque this); /** * Retrieves, but does not remove, the first element of this deque. @@ -340,7 +343,7 @@ public interface Deque extends Queue { * @throws NoSuchElementException if this deque is empty */ @EnsuresNonEmpty("this") - E getFirst(@GuardSatisfied @NonEmpty Deque this); + E getFirst(@GuardSatisfied @NonEmpty @Shrinkable Deque this); /** * Retrieves, but does not remove, the last element of this deque. @@ -351,7 +354,7 @@ public interface Deque extends Queue { * @throws NoSuchElementException if this deque is empty */ @EnsuresNonEmpty("this") - E getLast(@GuardSatisfied @NonEmpty Deque this); + E getLast(@GuardSatisfied @NonEmpty @Shrinkable Deque this); /** * Retrieves, but does not remove, the first element of this deque, @@ -388,7 +391,7 @@ public interface Deque extends Queue { * deque does not permit null elements * (optional) */ - boolean removeFirstOccurrence(@GuardSatisfied Deque this, Object o); + boolean removeFirstOccurrence(@GuardSatisfied @Shrinkable Deque this, Object o); /** * Removes the last occurrence of the specified element from this deque. @@ -407,7 +410,7 @@ public interface Deque extends Queue { * deque does not permit null elements * (optional) */ - boolean removeLastOccurrence(@GuardSatisfied Deque this, Object o); + boolean removeLastOccurrence(@GuardSatisfied @Shrinkable Deque this, Object o); // *** Queue methods *** @@ -470,7 +473,7 @@ public interface Deque extends Queue { * @return the head of the queue represented by this deque * @throws NoSuchElementException if this deque is empty */ - E remove(@GuardSatisfied @NonEmpty Deque this); + E remove(@GuardSatisfied @NonEmpty @Shrinkable Deque this); /** * Retrieves and removes the head of the queue represented by this deque @@ -482,7 +485,7 @@ public interface Deque extends Queue { * @return the first element of this deque, or {@code null} if * this deque is empty */ - @Nullable E poll(@GuardSatisfied Deque this); + @Nullable E poll(@GuardSatisfied @Shrinkable Deque this); /** * Retrieves, but does not remove, the head of the queue represented by @@ -568,7 +571,7 @@ public interface Deque extends Queue { * of the stack represented by this deque) * @throws NoSuchElementException if this deque is empty */ - E pop(@GuardSatisfied @NonEmpty Deque this); + E pop(@GuardSatisfied @NonEmpty @Shrinkable Deque this); // *** Collection methods *** @@ -592,7 +595,7 @@ public interface Deque extends Queue { * deque does not permit null elements * (optional) */ - boolean remove(@GuardSatisfied Deque this, @UnknownSignedness Object o); + boolean remove(@GuardSatisfied @Shrinkable Deque this, @UnknownSignedness Object o); /** * Returns {@code true} if this deque contains the specified element. @@ -627,7 +630,7 @@ public interface Deque extends Queue { * @return an iterator over the elements in this deque in proper sequence */ @SideEffectFree - Iterator iterator(); + @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty Deque this); /** * Returns an iterator over the elements in this deque in reverse diff --git a/src/java.base/share/classes/java/util/HashSet.java b/src/java.base/share/classes/java/util/HashSet.java index 60c0692c5c2..3fbb7d3f7be 100644 --- a/src/java.base/share/classes/java/util/HashSet.java +++ b/src/java.base/share/classes/java/util/HashSet.java @@ -26,6 +26,7 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -185,7 +186,7 @@ public HashSet(@NonNegative int initialCapacity) { * @see ConcurrentModificationException */ @SideEffectFree - public @PolyNonEmpty Iterator iterator(@PolyNonEmpty HashSet this) { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty HashSet this) { return map.keySet().iterator(); } diff --git a/src/java.base/share/classes/java/util/Iterator.java b/src/java.base/share/classes/java/util/Iterator.java index 1e0d65349c6..6bff1b79443 100644 --- a/src/java.base/share/classes/java/util/Iterator.java +++ b/src/java.base/share/classes/java/util/Iterator.java @@ -25,6 +25,7 @@ package java.util; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; @@ -113,7 +114,7 @@ public interface Iterator { * been called after the last call to the {@code next} * method */ - default void remove(@GuardSatisfied Iterator this) { + default void remove(@GuardSatisfied @Shrinkable Iterator this) { throw new UnsupportedOperationException("remove"); } diff --git a/src/java.base/share/classes/java/util/JumboEnumSet.java b/src/java.base/share/classes/java/util/JumboEnumSet.java index bbe9927f8fa..1c1691ef1b1 100644 --- a/src/java.base/share/classes/java/util/JumboEnumSet.java +++ b/src/java.base/share/classes/java/util/JumboEnumSet.java @@ -25,10 +25,12 @@ package java.util; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -107,7 +109,7 @@ void complement() { * * @return an iterator over the elements contained in this set */ - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty JumboEnumSet this) { return new EnumSetIterator<>(); } diff --git a/src/java.base/share/classes/java/util/LinkedList.java b/src/java.base/share/classes/java/util/LinkedList.java index 745be1b9b5b..fd97ba75fa8 100644 --- a/src/java.base/share/classes/java/util/LinkedList.java +++ b/src/java.base/share/classes/java/util/LinkedList.java @@ -27,6 +27,8 @@ import org.checkerframework.checker.index.qual.GTENegativeOne; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.lock.qual.ReleasesNoLocks; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; @@ -287,7 +289,7 @@ public E getLast(@GuardSatisfied @NonEmpty LinkedList this) { * @return the first element from this list * @throws NoSuchElementException if this list is empty */ - public E removeFirst(@GuardSatisfied @NonEmpty LinkedList this) { + public E removeFirst(@GuardSatisfied @NonEmpty @Shrinkable LinkedList this) { final Node f = first; if (f == null) throw new NoSuchElementException(); @@ -300,7 +302,7 @@ public E removeFirst(@GuardSatisfied @NonEmpty LinkedList this) { * @return the last element from this list * @throws NoSuchElementException if this list is empty */ - public E removeLast(@GuardSatisfied @NonEmpty LinkedList this) { + public E removeLast(@GuardSatisfied @NonEmpty @Shrinkable LinkedList this) { final Node l = last; if (l == null) throw new NoSuchElementException(); @@ -381,7 +383,7 @@ public boolean add(@GuardSatisfied LinkedList this, E e) { * @return {@code true} if this list contained the specified element */ @ReleasesNoLocks - public boolean remove(@GuardSatisfied LinkedList this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@GuardSatisfied @Shrinkable LinkedList this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o == null) { for (Node x = first; x != null; x = x.next) { if (x.item == null) { @@ -474,7 +476,7 @@ public boolean addAll(@GuardSatisfied LinkedList this, @NonNegative int index * Removes all of the elements from this list. * The list will be empty after this call returns. */ - public void clear(@GuardSatisfied LinkedList this) { + public void clear(@GuardSatisfied @Shrinkable LinkedList this) { // Clearing all of the links between nodes is "unnecessary", but: // - helps a generational GC if the discarded nodes inhabit // more than one generation @@ -551,7 +553,7 @@ public void add(@GuardSatisfied LinkedList this, @NonNegative int index, E el * @return the element previously at the specified position * @throws IndexOutOfBoundsException {@inheritDoc} */ - public E remove(@GuardSatisfied LinkedList this, @NonNegative int index) { + public E remove(@GuardSatisfied @Shrinkable LinkedList this, @NonNegative int index) { checkElementIndex(index); return unlink(node(index)); } @@ -702,7 +704,7 @@ public E element(@GuardSatisfied @NonEmpty LinkedList this) { * @return the head of this list, or {@code null} if this list is empty * @since 1.5 */ - public @Nullable E poll(@GuardSatisfied LinkedList this) { + public @Nullable E poll(@GuardSatisfied @Shrinkable LinkedList this) { final Node f = first; return (f == null) ? null : unlinkFirst(f); } @@ -714,7 +716,7 @@ public E element(@GuardSatisfied @NonEmpty LinkedList this) { * @throws NoSuchElementException if this list is empty * @since 1.5 */ - public E remove(@GuardSatisfied @NonEmpty LinkedList this) { + public E remove(@GuardSatisfied @NonEmpty @Shrinkable LinkedList this) { return removeFirst(); } @@ -790,7 +792,7 @@ public boolean offerLast(E e) { * this list is empty * @since 1.6 */ - public @Nullable E pollFirst(@GuardSatisfied LinkedList this) { + public @Nullable E pollFirst(@GuardSatisfied @Shrinkable LinkedList this) { final Node f = first; return (f == null) ? null : unlinkFirst(f); } @@ -803,7 +805,7 @@ public boolean offerLast(E e) { * this list is empty * @since 1.6 */ - public @Nullable E pollLast(@GuardSatisfied LinkedList this) { + public @Nullable E pollLast(@GuardSatisfied @Shrinkable LinkedList this) { final Node l = last; return (l == null) ? null : unlinkLast(l); } @@ -832,7 +834,7 @@ public void push(@GuardSatisfied LinkedList this, E e) { * @throws NoSuchElementException if this list is empty * @since 1.6 */ - public E pop(@GuardSatisfied @NonEmpty LinkedList this) { + public E pop(@GuardSatisfied @NonEmpty @Shrinkable LinkedList this) { return removeFirst(); } @@ -845,7 +847,7 @@ public E pop(@GuardSatisfied @NonEmpty LinkedList this) { * @return {@code true} if the list contained the specified element * @since 1.6 */ - public boolean removeFirstOccurrence(@GuardSatisfied LinkedList this, @Nullable Object o) { + public boolean removeFirstOccurrence(@GuardSatisfied @Shrinkable LinkedList this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { return remove(o); } @@ -858,7 +860,7 @@ public boolean removeFirstOccurrence(@GuardSatisfied LinkedList this, @Nullab * @return {@code true} if the list contained the specified element * @since 1.6 */ - public boolean removeLastOccurrence(@GuardSatisfied LinkedList this, @Nullable Object o) { + public boolean removeLastOccurrence(@GuardSatisfied @Shrinkable LinkedList this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o == null) { for (Node x = last; x != null; x = x.prev) { if (x.item == null) { @@ -898,7 +900,7 @@ public boolean removeLastOccurrence(@GuardSatisfied LinkedList this, @Nullabl * @throws IndexOutOfBoundsException {@inheritDoc} * @see List#listIterator(int) */ - public ListIterator listIterator(@NonNegative int index) { + public @PolyGrowShrink @PolyNonEmpty ListIterator listIterator(@PolyGrowShrink @PolyNonEmpty LinkedList this, @NonNegative int index) { checkPositionIndex(index); return new ListItr(index); } @@ -1019,7 +1021,7 @@ private static class Node { /** * @since 1.6 */ - public Iterator descendingIterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator descendingIterator(@PolyGrowShrink @PolyNonEmpty LinkedList this) { return new DescendingIterator(); } diff --git a/src/java.base/share/classes/java/util/List.java b/src/java.base/share/classes/java/util/List.java index 59c21c097f8..2974d407771 100644 --- a/src/java.base/share/classes/java/util/List.java +++ b/src/java.base/share/classes/java/util/List.java @@ -29,6 +29,8 @@ import org.checkerframework.checker.index.qual.IndexFor; import org.checkerframework.checker.index.qual.IndexOrHigh; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.lock.qual.ReleasesNoLocks; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; @@ -207,7 +209,7 @@ public interface List extends Collection { * @return an iterator over the elements in this list in proper sequence */ @SideEffectFree - @PolyNonEmpty Iterator iterator(@PolyNonEmpty List this); + @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty List this); /** * Returns an array containing all of the elements in this list in proper @@ -320,7 +322,7 @@ public interface List extends Collection { * @throws UnsupportedOperationException if the {@code remove} operation * is not supported by this list */ - boolean remove(@GuardSatisfied List this, @UnknownSignedness Object o); + boolean remove(@GuardSatisfied @Shrinkable List this, @UnknownSignedness Object o); // Bulk Modification Operations @@ -418,7 +420,7 @@ public interface List extends Collection { * @see #remove(Object) * @see #contains(Object) */ - boolean removeAll(@GuardSatisfied List this, Collection c); + boolean removeAll(@GuardSatisfied @Shrinkable List this, Collection c); /** * Retains only the elements in this list that are contained in the @@ -440,7 +442,7 @@ public interface List extends Collection { * @see #remove(Object) * @see #contains(Object) */ - boolean retainAll(@GuardSatisfied List this, Collection c); + boolean retainAll(@GuardSatisfied @Shrinkable List this, Collection c); /** * Replaces each element of this list with the result of applying the @@ -556,7 +558,7 @@ default void sort(@Nullable Comparator c) { * @throws UnsupportedOperationException if the {@code clear} operation * is not supported by this list */ - void clear(@GuardSatisfied List this); + void clear(@GuardSatisfied @Shrinkable List this); // Comparison and hashing @@ -668,7 +670,7 @@ default void sort(@Nullable Comparator c) { * ({@code index < 0 || index >= size()}) */ @ReleasesNoLocks - E remove(@GuardSatisfied List this, @IndexFor({"this"}) int index); + E remove(@GuardSatisfied @Shrinkable List this, @IndexFor({"this"}) int index); // Search Operations @@ -723,7 +725,7 @@ default void sort(@Nullable Comparator c) { * @return a list iterator over the elements in this list (in proper * sequence) */ - ListIterator listIterator(); + @PolyGrowShrink @PolyNonEmpty ListIterator listIterator(@PolyGrowShrink @PolyNonEmpty List this); /** * Returns a list iterator over the elements in this list (in proper @@ -740,7 +742,7 @@ default void sort(@Nullable Comparator c) { * @throws IndexOutOfBoundsException if the index is out of range * ({@code index < 0 || index > size()}) */ - ListIterator listIterator(@IndexOrHigh({"this"}) int index); + @PolyGrowShrink @PolyNonEmpty ListIterator listIterator(@PolyGrowShrink @PolyNonEmpty List this, @IndexOrHigh({"this"}) int index); // View @@ -779,7 +781,7 @@ default void sort(@Nullable Comparator c) { * fromIndex > toIndex}) */ @SideEffectFree - List subList(@GuardSatisfied List this, @IndexOrHigh({"this"}) int fromIndex, @IndexOrHigh({"this"}) int toIndex); + @PolyGrowShrink List subList(@GuardSatisfied @PolyGrowShrink List this, @IndexOrHigh({"this"}) int fromIndex, @IndexOrHigh({"this"}) int toIndex); /** * Creates a {@link Spliterator} over the elements in this list. diff --git a/src/java.base/share/classes/java/util/NavigableSet.java b/src/java.base/share/classes/java/util/NavigableSet.java index 1f742334eb7..f151aa4a591 100644 --- a/src/java.base/share/classes/java/util/NavigableSet.java +++ b/src/java.base/share/classes/java/util/NavigableSet.java @@ -35,7 +35,9 @@ package java.util; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -174,7 +176,7 @@ public interface NavigableSet extends SortedSet { * @return an iterator over the elements in this set, in ascending order */ @SideEffectFree - Iterator iterator(); + @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty NavigableSet this); /** * Returns a reverse order view of the elements contained in this set. diff --git a/src/java.base/share/classes/java/util/PriorityQueue.java b/src/java.base/share/classes/java/util/PriorityQueue.java index faa59d5f886..9cd7735b994 100644 --- a/src/java.base/share/classes/java/util/PriorityQueue.java +++ b/src/java.base/share/classes/java/util/PriorityQueue.java @@ -26,7 +26,9 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.index.qual.Positive; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -378,7 +380,7 @@ private int indexOf(@GuardSatisfied @Nullable @UnknownSignedness Object o) { * @param o element to be removed from this queue, if present * @return {@code true} if this queue changed as a result of the call */ - public boolean remove(@GuardSatisfied PriorityQueue this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@GuardSatisfied @Shrinkable PriorityQueue this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { int i = indexOf(o); if (i == -1) return false; @@ -393,7 +395,7 @@ public boolean remove(@GuardSatisfied PriorityQueue this, @GuardSatisfied @Nu * * @param o element to be removed from this queue, if present */ - void removeEq(Object o) { + void removeEq(@GuardSatisfied @Shrinkable PriorityQueue this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { final Object[] es = queue; for (int i = 0, n = size; i < n; i++) { if (o == es[i]) { @@ -490,7 +492,7 @@ public boolean contains(@GuardSatisfied PriorityQueue this, @GuardSatisfied @ * @return an iterator over the elements in this queue */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty PriorityQueue this) { return new Itr(); } @@ -589,7 +591,7 @@ public void remove() { * Removes all of the elements from this priority queue. * The queue will be empty after this call returns. */ - public void clear(@GuardSatisfied PriorityQueue this) { + public void clear(@GuardSatisfied @Shrinkable PriorityQueue this) { modCount++; final Object[] es = queue; for (int i = 0, n = size; i < n; i++) @@ -597,7 +599,7 @@ public void clear(@GuardSatisfied PriorityQueue this) { size = 0; } - public @Nullable E poll(@GuardSatisfied PriorityQueue this) { + public @Nullable E poll(@GuardSatisfied @Shrinkable PriorityQueue this) { final Object[] es; final E result; @@ -629,7 +631,7 @@ public void clear(@GuardSatisfied PriorityQueue this) { * position before i. This fact is used by iterator.remove so as to * avoid missing traversing elements. */ - E removeAt(int i) { + E removeAt(@GuardSatisfied @NonEmpty @Shrinkable PriorityQueue this, int i) { // assert i >= 0 && i < size; final Object[] es = queue; modCount++; @@ -920,7 +922,7 @@ public int characteristics() { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@GuardSatisfied @Shrinkable PriorityQueue this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -928,7 +930,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@GuardSatisfied @Shrinkable PriorityQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -936,7 +938,7 @@ public boolean removeAll(Collection c) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean retainAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable PriorityQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } diff --git a/src/java.base/share/classes/java/util/Queue.java b/src/java.base/share/classes/java/util/Queue.java index e72a674119e..81af386824e 100644 --- a/src/java.base/share/classes/java/util/Queue.java +++ b/src/java.base/share/classes/java/util/Queue.java @@ -35,6 +35,7 @@ package java.util; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -194,7 +195,7 @@ public interface Queue extends Collection { * @return the head of this queue * @throws NoSuchElementException if this queue is empty */ - E remove(@GuardSatisfied @NonEmpty Queue this); + E remove(@GuardSatisfied @NonEmpty @Shrinkable Queue this); /** * Retrieves and removes the head of this queue, @@ -202,7 +203,7 @@ public interface Queue extends Collection { * * @return the head of this queue, or {@code null} if this queue is empty */ - @Nullable E poll(@GuardSatisfied Queue this); + @Nullable E poll(@GuardSatisfied @Shrinkable Queue this); /** * Retrieves, but does not remove, the head of this queue. This method diff --git a/src/java.base/share/classes/java/util/RegularEnumSet.java b/src/java.base/share/classes/java/util/RegularEnumSet.java index 866e58fe11c..b79d019efa0 100644 --- a/src/java.base/share/classes/java/util/RegularEnumSet.java +++ b/src/java.base/share/classes/java/util/RegularEnumSet.java @@ -26,10 +26,12 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -86,7 +88,7 @@ void complement() { * * @return an iterator over the elements contained in this set */ - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty RegularEnumSet this) { return new EnumSetIterator<>(); } diff --git a/src/java.base/share/classes/java/util/Set.java b/src/java.base/share/classes/java/util/Set.java index 3e3dda8e533..0db338eaaeb 100644 --- a/src/java.base/share/classes/java/util/Set.java +++ b/src/java.base/share/classes/java/util/Set.java @@ -26,6 +26,7 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -178,7 +179,7 @@ public interface Set extends Collection { * @return an iterator over the elements in this set */ @SideEffectFree - @PolyNonEmpty Iterator iterator(@PolyNonEmpty Set this); + @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty Set this); /** * Returns an array containing all of the elements in this set. diff --git a/src/java.base/share/classes/java/util/Stack.java b/src/java.base/share/classes/java/util/Stack.java index 6bb22a593e6..76a14a600ec 100644 --- a/src/java.base/share/classes/java/util/Stack.java +++ b/src/java.base/share/classes/java/util/Stack.java @@ -25,8 +25,10 @@ package java.util; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -85,7 +87,7 @@ public E push(@GuardSatisfied Stack this, E item) { * of the {@code Vector} object). * @throws EmptyStackException if this stack is empty. */ - public synchronized E pop(@GuardSatisfied Stack this) { + public synchronized E pop(@GuardSatisfied @NonEmpty @Shrinkable Stack this) { E obj; int len = size(); diff --git a/src/java.base/share/classes/java/util/TreeSet.java b/src/java.base/share/classes/java/util/TreeSet.java index 1763fbf81de..ce8e1c663d1 100644 --- a/src/java.base/share/classes/java/util/TreeSet.java +++ b/src/java.base/share/classes/java/util/TreeSet.java @@ -26,6 +26,7 @@ package java.util; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -194,7 +195,7 @@ public TreeSet(@Nullable Comparator comparator) { * @return an iterator over the elements in this set in ascending order */ @SideEffectFree - public @PolyNonEmpty Iterator iterator(@PolyNonEmpty TreeSet this) { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty TreeSet this) { return m.navigableKeySet().iterator(); } @@ -204,7 +205,7 @@ public TreeSet(@Nullable Comparator comparator) { * @return an iterator over the elements in this set in descending order * @since 1.6 */ - public @PolyNonEmpty Iterator descendingIterator(@PolyNonEmpty TreeSet this) { + public @PolyGrowShrink @PolyNonEmpty Iterator descendingIterator(@PolyGrowShrink @PolyNonEmpty TreeSet this) { return m.descendingKeySet().iterator(); } @@ -342,7 +343,7 @@ public boolean addAll(@GuardSatisfied TreeSet this, Collection * @since 1.6 */ @SideEffectFree - public NavigableSet subSet(@GuardSatisfied TreeSet this, @GuardSatisfied E fromElement, boolean fromInclusive, + public @PolyGrowShrink NavigableSet subSet(@GuardSatisfied @PolyGrowShrink TreeSet this, @GuardSatisfied E fromElement, boolean fromInclusive, @GuardSatisfied E toElement, boolean toInclusive) { return new TreeSet<>(m.subMap(fromElement, fromInclusive, toElement, toInclusive)); @@ -357,7 +358,7 @@ public NavigableSet subSet(@GuardSatisfied TreeSet this, @GuardSatisfied E * @since 1.6 */ @SideEffectFree - public NavigableSet headSet(@GuardSatisfied TreeSet this, @GuardSatisfied E toElement, boolean inclusive) { + public @PolyGrowShrink NavigableSet headSet(@GuardSatisfied @PolyGrowShrink TreeSet this, @GuardSatisfied E toElement, boolean inclusive) { return new TreeSet<>(m.headMap(toElement, inclusive)); } @@ -370,7 +371,7 @@ public NavigableSet headSet(@GuardSatisfied TreeSet this, @GuardSatisfied * @since 1.6 */ @SideEffectFree - public NavigableSet tailSet(@GuardSatisfied TreeSet this, @GuardSatisfied E fromElement, boolean inclusive) { + public @PolyGrowShrink NavigableSet tailSet(@GuardSatisfied @PolyGrowShrink TreeSet this, @GuardSatisfied E fromElement, boolean inclusive) { return new TreeSet<>(m.tailMap(fromElement, inclusive)); } @@ -382,7 +383,7 @@ public NavigableSet tailSet(@GuardSatisfied TreeSet this, @GuardSatisfied * @throws IllegalArgumentException {@inheritDoc} */ @SideEffectFree - public SortedSet subSet(@GuardSatisfied TreeSet this, @GuardSatisfied E fromElement, @GuardSatisfied E toElement) { + public @PolyGrowShrink SortedSet subSet(@GuardSatisfied @PolyGrowShrink TreeSet this, @GuardSatisfied E fromElement, @GuardSatisfied E toElement) { return subSet(fromElement, true, toElement, false); } @@ -394,7 +395,7 @@ public SortedSet subSet(@GuardSatisfied TreeSet this, @GuardSatisfied E fr * @throws IllegalArgumentException {@inheritDoc} */ @SideEffectFree - public SortedSet headSet(@GuardSatisfied TreeSet this, E toElement) { + public @PolyGrowShrink SortedSet headSet(@GuardSatisfied @PolyGrowShrink TreeSet this, E toElement) { return headSet(toElement, false); } @@ -406,7 +407,7 @@ public SortedSet headSet(@GuardSatisfied TreeSet this, E toElement) { * @throws IllegalArgumentException {@inheritDoc} */ @SideEffectFree - public SortedSet tailSet(@GuardSatisfied TreeSet this, E fromElement) { + public @PolyGrowShrink SortedSet tailSet(@GuardSatisfied @PolyGrowShrink TreeSet this, E fromElement) { return tailSet(fromElement, true); } diff --git a/src/java.base/share/classes/java/util/Vector.java b/src/java.base/share/classes/java/util/Vector.java index d603fae2f34..f6a71faefe2 100644 --- a/src/java.base/share/classes/java/util/Vector.java +++ b/src/java.base/share/classes/java/util/Vector.java @@ -27,6 +27,8 @@ import org.checkerframework.checker.index.qual.GTENegativeOne; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -293,7 +295,7 @@ private Object[] grow() { * @param newSize the new size of this vector * @throws ArrayIndexOutOfBoundsException if the new size is negative */ - public synchronized void setSize(@GuardSatisfied Vector this, @NonNegative int newSize) { + public synchronized void setSize(@GuardSatisfied @Shrinkable Vector this, @NonNegative int newSize) { modCount++; if (newSize > elementData.length) grow(newSize); @@ -348,7 +350,7 @@ public synchronized boolean isEmpty(@GuardSatisfied Vector this) { * @return an enumeration of the components of this vector * @see Iterator */ - public Enumeration elements() { + public @PolyGrowShrink @PolyNonEmpty Enumeration elements(@PolyGrowShrink @PolyNonEmpty Vector this) { return new Enumeration() { int count = 0; @@ -572,7 +574,7 @@ public synchronized void setElementAt(@GuardSatisfied Vector this, E obj, @No * @throws ArrayIndexOutOfBoundsException if the index is out of range * ({@code index < 0 || index >= size()}) */ - public synchronized void removeElementAt(@GuardSatisfied Vector this, @NonNegative int index) { + public synchronized void removeElementAt(@GuardSatisfied @Shrinkable Vector this, @NonNegative int index) { if (index >= elementCount) { throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount); @@ -660,7 +662,7 @@ public synchronized void addElement(@GuardSatisfied Vector this, E obj) { * @return {@code true} if the argument was a component of this * vector; {@code false} otherwise. */ - public synchronized boolean removeElement(@GuardSatisfied Vector this, Object obj) { + public synchronized boolean removeElement(@GuardSatisfied @Shrinkable Vector this, Object obj) { modCount++; int i = indexOf(obj); if (i >= 0) { @@ -676,7 +678,7 @@ public synchronized boolean removeElement(@GuardSatisfied Vector this, Object *

      This method is identical in functionality to the {@link #clear} * method (which is part of the {@link List} interface). */ - public synchronized void removeAllElements(@GuardSatisfied Vector this) { + public synchronized void removeAllElements(@GuardSatisfied @Shrinkable Vector this) { final Object[] es = elementData; for (int to = elementCount, i = elementCount = 0; i < to; i++) es[i] = null; @@ -841,7 +843,7 @@ public synchronized boolean add(@GuardSatisfied Vector this, E e) { * @return true if the Vector contained the specified element * @since 1.2 */ - public boolean remove(@GuardSatisfied Vector this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@GuardSatisfied @Shrinkable Vector this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { return removeElement(o); } @@ -871,7 +873,7 @@ public void add(@GuardSatisfied Vector this, @NonNegative int index, E elemen * ({@code index < 0 || index >= size()}) * @since 1.2 */ - public synchronized E remove(@GuardSatisfied Vector this, @NonNegative int index) { + public synchronized E remove(@GuardSatisfied @Shrinkable Vector this, @NonNegative int index) { modCount++; if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); @@ -892,7 +894,7 @@ public synchronized E remove(@GuardSatisfied Vector this, @NonNegative int in * * @since 1.2 */ - public void clear(@GuardSatisfied Vector this) { + public void clear(@GuardSatisfied @Shrinkable Vector this) { removeAllElements(); } @@ -960,7 +962,7 @@ public boolean addAll(@GuardSatisfied Vector this, Collection c) * or if the specified collection is null * @since 1.2 */ - public boolean removeAll(@GuardSatisfied Vector this, Collection c) { + public boolean removeAll(@GuardSatisfied @Shrinkable Vector this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -984,7 +986,7 @@ public boolean removeAll(@GuardSatisfied Vector this, Collection this, Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable Vector this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } @@ -994,7 +996,7 @@ public boolean retainAll(@GuardSatisfied Vector this, Collection filter) { + public boolean removeIf(@Shrinkable Vector this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -1156,7 +1158,7 @@ public synchronized String toString(@GuardSatisfied Vector this) { * {@code (fromIndex > toIndex)} */ @SideEffectFree - public synchronized List subList(@GuardSatisfied Vector this, int fromIndex, int toIndex) { + public synchronized @PolyGrowShrink List subList(@GuardSatisfied @PolyGrowShrink Vector this, int fromIndex, int toIndex) { return Collections.synchronizedList(super.subList(fromIndex, toIndex), this); } @@ -1168,7 +1170,7 @@ public synchronized List subList(@GuardSatisfied Vector this, int fromInde * This call shortens the list by {@code (toIndex - fromIndex)} elements. * (If {@code toIndex==fromIndex}, this operation has no effect.) */ - protected synchronized void removeRange(int fromIndex, int toIndex) { + protected synchronized void removeRange(@GuardSatisfied @Shrinkable Vector this, int fromIndex, int toIndex) { modCount++; shiftTailOverGap(elementData, fromIndex, toIndex); } @@ -1239,7 +1241,7 @@ private void writeObject(java.io.ObjectOutputStream s) * * @throws IndexOutOfBoundsException {@inheritDoc} */ - public synchronized ListIterator listIterator(@NonNegative int index) { + public synchronized @PolyGrowShrink ListIterator listIterator(@PolyGrowShrink Vector this, @NonNegative int index) { if (index < 0 || index > elementCount) throw new IndexOutOfBoundsException("Index: "+index); return new ListItr(index); @@ -1253,7 +1255,7 @@ public synchronized ListIterator listIterator(@NonNegative int index) { * * @see #listIterator(int) */ - public synchronized ListIterator listIterator() { + public synchronized @PolyGrowShrink @PolyNonEmpty ListIterator listIterator(@PolyGrowShrink Vector this) { return new ListItr(0); } @@ -1265,7 +1267,7 @@ public synchronized ListIterator listIterator() { * @return an iterator over the elements in this list in proper sequence */ @SideEffectFree - public synchronized Iterator iterator() { + public synchronized @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty Vector this) { return new Itr(); } diff --git a/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java index 0b22a67b0c7..f322ca81700 100644 --- a/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java @@ -35,10 +35,13 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -416,7 +419,7 @@ public boolean offer(E e, long timeout, TimeUnit unit) } } - public @Nullable E poll() { + public @Nullable E poll(@GuardSatisfied @Shrinkable ArrayBlockingQueue this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -426,7 +429,7 @@ public boolean offer(E e, long timeout, TimeUnit unit) } } - public E take() throws InterruptedException { + public E take(@GuardSatisfied @Shrinkable ArrayBlockingQueue this) throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { @@ -438,7 +441,7 @@ public E take() throws InterruptedException { } } - public @Nullable E poll(long timeout, TimeUnit unit) throws InterruptedException { + public @Nullable E poll(@GuardSatisfied @Shrinkable ArrayBlockingQueue this, long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); @@ -523,7 +526,7 @@ public int remainingCapacity() { * @param o element to be removed from this queue, if present * @return {@code true} if this queue changed as a result of the call */ - public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@Shrinkable ArrayBlockingQueue this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o == null) return false; final ReentrantLock lock = this.lock; lock.lock(); @@ -674,7 +677,7 @@ public String toString() { * Atomically removes all of the elements from this queue. * The queue will be empty after this call returns. */ - public void clear() { + public void clear(@GuardSatisfied @Shrinkable ArrayBlockingQueue this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -713,7 +716,7 @@ private static void circularClear(Object[] items, int i, int end) { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c) { + public int drainTo(@GuardSatisfied @Shrinkable ArrayBlockingQueue this, Collection c) { return drainTo(c, Integer.MAX_VALUE); } @@ -723,7 +726,7 @@ public int drainTo(Collection c) { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c, int maxElements) { + public int drainTo(@GuardSatisfied @Shrinkable ArrayBlockingQueue this, Collection c, int maxElements) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); @@ -775,7 +778,7 @@ else if (i > take) * * @return an iterator over the elements in this queue in proper sequence */ - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty ArrayBlockingQueue this) { return new Itr(); } @@ -1488,7 +1491,7 @@ public void forEach(Consumer action) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable ArrayBlockingQueue this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -1496,7 +1499,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable ArrayBlockingQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1504,7 +1507,7 @@ public boolean removeAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable ArrayBlockingQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } diff --git a/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java b/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java index 19c69c78465..6356ee6d378 100644 --- a/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java @@ -35,9 +35,13 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; +import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.signedness.qual.UnknownSignedness; @@ -355,7 +359,7 @@ boolean offerLast(E e, long timeout, TimeUnit unit) * @return the head of this deque * @throws InterruptedException if interrupted while waiting */ - E takeFirst() throws InterruptedException; + E takeFirst(@Shrinkable BlockingDeque this) throws InterruptedException; /** * Retrieves and removes the last element of this deque, waiting @@ -364,7 +368,7 @@ boolean offerLast(E e, long timeout, TimeUnit unit) * @return the tail of this deque * @throws InterruptedException if interrupted while waiting */ - E takeLast() throws InterruptedException; + E takeLast(@Shrinkable BlockingDeque this) throws InterruptedException; /** * Retrieves and removes the first element of this deque, waiting @@ -379,7 +383,7 @@ boolean offerLast(E e, long timeout, TimeUnit unit) * waiting time elapses before an element is available * @throws InterruptedException if interrupted while waiting */ - @Nullable E pollFirst(long timeout, TimeUnit unit) + @Nullable E pollFirst(@Shrinkable BlockingDeque this, long timeout, TimeUnit unit) throws InterruptedException; /** @@ -395,7 +399,7 @@ boolean offerLast(E e, long timeout, TimeUnit unit) * waiting time elapses before an element is available * @throws InterruptedException if interrupted while waiting */ - @Nullable E pollLast(long timeout, TimeUnit unit) + @Nullable E pollLast(@Shrinkable BlockingDeque this, long timeout, TimeUnit unit) throws InterruptedException; /** @@ -414,7 +418,7 @@ boolean offerLast(E e, long timeout, TimeUnit unit) * @throws NullPointerException if the specified element is null * (optional) */ - boolean removeFirstOccurrence(Object o); + boolean removeFirstOccurrence(@Shrinkable BlockingDeque this, Object o); /** * Removes the last occurrence of the specified element from this deque. @@ -432,7 +436,7 @@ boolean offerLast(E e, long timeout, TimeUnit unit) * @throws NullPointerException if the specified element is null * (optional) */ - boolean removeLastOccurrence(Object o); + boolean removeLastOccurrence(@Shrinkable BlockingDeque this, Object o); // *** BlockingQueue methods *** @@ -527,7 +531,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * @return the head of the queue represented by this deque * @throws NoSuchElementException if this deque is empty */ - E remove(@NonEmpty BlockingDeque this); + E remove(@GuardSatisfied @NonEmpty @Shrinkable BlockingDeque this); /** * Retrieves and removes the head of the queue represented by this deque @@ -538,7 +542,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * * @return the head of this deque, or {@code null} if this deque is empty */ - @Nullable E poll(); + @Nullable E poll(@Shrinkable BlockingDeque this); /** * Retrieves and removes the head of the queue represented by this deque @@ -550,7 +554,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * @return the head of this deque * @throws InterruptedException if interrupted while waiting */ - E take() throws InterruptedException; + E take(@Shrinkable BlockingDeque this) throws InterruptedException; /** * Retrieves and removes the head of the queue represented by this deque @@ -564,7 +568,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * specified waiting time elapses before an element is available * @throws InterruptedException if interrupted while waiting */ - @Nullable E poll(long timeout, TimeUnit unit) + @Nullable E poll(@Shrinkable BlockingDeque this, long timeout, TimeUnit unit) throws InterruptedException; /** @@ -611,7 +615,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * @throws NullPointerException if the specified element is null * (optional) */ - boolean remove(@UnknownSignedness Object o); + boolean remove(@Shrinkable BlockingDeque this, @UnknownSignedness Object o); /** * Returns {@code true} if this deque contains the specified element. @@ -645,7 +649,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * @return an iterator over the elements in this deque in proper sequence */ @SideEffectFree - Iterator iterator(); + @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty BlockingDeque this); // *** Stack methods *** diff --git a/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java index b4e99d9d203..7ad116a16c3 100644 --- a/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java @@ -35,6 +35,8 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.Shrinkable; +import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; @@ -317,7 +319,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * @throws NullPointerException if the specified element is null * (optional) */ - boolean remove(@UnknownSignedness Object o); + boolean remove(@Shrinkable BlockingQueue this, @UnknownSignedness Object o); /** * Returns {@code true} if this queue contains the specified element. @@ -359,7 +361,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * queue, or some property of an element of this queue prevents * it from being added to the specified collection */ - int drainTo(Collection c); + int drainTo(@GuardSatisfied @Shrinkable BlockingQueue this, Collection c); /** * Removes at most the given number of available elements from @@ -384,5 +386,5 @@ boolean offer(E e, long timeout, TimeUnit unit) * queue, or some property of an element of this queue prevents * it from being added to the specified collection */ - int drainTo(Collection c, int maxElements); + int drainTo(@GuardSatisfied @Shrinkable BlockingQueue this, Collection c, int maxElements); } diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java index 455ddf84ff6..e5c0c9964c2 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java @@ -35,10 +35,13 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -927,7 +930,7 @@ public E getLast(@NonEmpty ConcurrentLinkedDeque this) { return screenNullResult(peekLast()); } - public @Nullable E pollFirst() { + public @Nullable E pollFirst(@GuardSatisfied @Shrinkable ConcurrentLinkedDeque this) { restart: for (;;) { for (Node first = first(), p = first;;) { final E item; @@ -948,7 +951,7 @@ public E getLast(@NonEmpty ConcurrentLinkedDeque this) { } } - public @Nullable E pollLast() { + public @Nullable E pollLast(@GuardSatisfied @Shrinkable ConcurrentLinkedDeque this) { restart: for (;;) { for (Node last = last(), p = last;;) { final E item; @@ -972,14 +975,14 @@ public E getLast(@NonEmpty ConcurrentLinkedDeque this) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeFirst(@NonEmpty ConcurrentLinkedDeque this) { + public E removeFirst(@GuardSatisfied @NonEmpty @Shrinkable ConcurrentLinkedDeque this) { return screenNullResult(pollFirst()); } /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeLast(@NonEmpty ConcurrentLinkedDeque this) { + public E removeLast(@GuardSatisfied @NonEmpty @Shrinkable ConcurrentLinkedDeque this) { return screenNullResult(pollLast()); } @@ -1009,19 +1012,19 @@ public boolean add(E e) { return offerLast(e); } - public @Nullable E poll() { return pollFirst(); } + public @Nullable E poll(@Shrinkable ConcurrentLinkedDeque this) { return pollFirst(); } @Pure public @Nullable E peek() { return peekFirst(); } /** * @throws NoSuchElementException {@inheritDoc} */ - public E remove(@NonEmpty ConcurrentLinkedDeque this) { return removeFirst(); } + public E remove(@NonEmpty @Shrinkable ConcurrentLinkedDeque this) { return removeFirst(); } /** * @throws NoSuchElementException {@inheritDoc} */ - public E pop(@NonEmpty ConcurrentLinkedDeque this) { return removeFirst(); } + public E pop(@GuardSatisfied @NonEmpty @Shrinkable ConcurrentLinkedDeque this) { return removeFirst(); } /** * @throws NoSuchElementException {@inheritDoc} @@ -1045,7 +1048,7 @@ public boolean add(E e) { * @return {@code true} if the deque contained the specified element * @throws NullPointerException if the specified element is null */ - public boolean removeFirstOccurrence(Object o) { + public boolean removeFirstOccurrence(@Shrinkable ConcurrentLinkedDeque this, Object o) { Objects.requireNonNull(o); for (Node p = first(); p != null; p = succ(p)) { final E item; @@ -1071,7 +1074,7 @@ public boolean removeFirstOccurrence(Object o) { * @return {@code true} if the deque contained the specified element * @throws NullPointerException if the specified element is null */ - public boolean removeLastOccurrence(Object o) { + public boolean removeLastOccurrence(@Shrinkable ConcurrentLinkedDeque this, Object o) { Objects.requireNonNull(o); for (Node p = last(); p != null; p = pred(p)) { final E item; @@ -1163,7 +1166,7 @@ public int size() { * @return {@code true} if the deque contained the specified element * @throws NullPointerException if the specified element is null */ - public boolean remove(@GuardSatisfied @UnknownSignedness Object o) { + public boolean remove(@Shrinkable ConcurrentLinkedDeque this, @GuardSatisfied @UnknownSignedness Object o) { return removeFirstOccurrence(o); } @@ -1233,7 +1236,7 @@ else if (p.prev == p) // NEXT_TERMINATOR /** * Removes all of the elements from this deque. */ - public void clear() { + public void clear(@GuardSatisfied @Shrinkable ConcurrentLinkedDeque this) { while (pollFirst() != null) ; } @@ -1366,7 +1369,7 @@ else if (a != null && size <= a.length) { * @return an iterator over the elements in this deque in proper sequence */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty ConcurrentLinkedDeque this) { return new Itr(); } @@ -1380,7 +1383,7 @@ public Iterator iterator() { * * @return an iterator over the elements in this deque in reverse order */ - public Iterator descendingIterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator descendingIterator(@PolyGrowShrink @PolyNonEmpty ConcurrentLinkedDeque this) { return new DescendingItr(); } @@ -1633,7 +1636,7 @@ private void readObject(java.io.ObjectInputStream s) /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable ConcurrentLinkedDeque this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -1641,7 +1644,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable ConcurrentLinkedDeque this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1649,7 +1652,7 @@ public boolean removeAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable ConcurrentLinkedDeque this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java index c57cb976688..5f8ccec2186 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java @@ -35,10 +35,13 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -395,7 +398,7 @@ else if (p == q) } } - public @Nullable E poll() { + public @Nullable E poll(@GuardSatisfied @Shrinkable ConcurrentLinkedQueue this) { restartFromHead: for (;;) { for (Node h = head, p = h, q;; p = q) { final E item; @@ -539,7 +542,7 @@ public boolean contains(@GuardSatisfied @UnknownSignedness Object o) { * @param o element to be removed from this queue, if present * @return {@code true} if this queue changed as a result of the call */ - public boolean remove(@GuardSatisfied @UnknownSignedness Object o) { + public boolean remove(@Shrinkable ConcurrentLinkedQueue this, @GuardSatisfied @UnknownSignedness Object o) { if (o == null) return false; restartFromHead: for (;;) { for (Node p = head, pred = null; p != null; ) { @@ -749,7 +752,7 @@ else if (a != null && size <= a.length) { * @return an iterator over the elements in this queue in proper sequence */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty ConcurrentLinkedQueue this) { return new Itr(); } @@ -986,7 +989,7 @@ public Spliterator spliterator() { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable ConcurrentLinkedQueue this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -994,7 +997,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable ConcurrentLinkedQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1002,12 +1005,12 @@ public boolean removeAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable ConcurrentLinkedQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } - public void clear() { + public void clear(@GuardSatisfied @Shrinkable ConcurrentLinkedQueue this) { bulkRemove(e -> true); } diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java index 11038b52fe6..6d3c1ce27aa 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java @@ -35,10 +35,12 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -294,7 +296,7 @@ public void clear() { * @return an iterator over the elements in this set in ascending order */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this) { return m.navigableKeySet().iterator(); } @@ -303,7 +305,7 @@ public Iterator iterator() { * * @return an iterator over the elements in this set in descending order */ - public Iterator descendingIterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator descendingIterator(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this) { return m.descendingKeySet().iterator(); } @@ -433,7 +435,7 @@ public E last(@NonEmpty ConcurrentSkipListSet this) { * {@code toElement} is null * @throws IllegalArgumentException {@inheritDoc} */ - public NavigableSet subSet(E fromElement, + public @PolyGrowShrink @PolyNonEmpty NavigableSet subSet(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this, E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { @@ -447,7 +449,7 @@ public NavigableSet subSet(E fromElement, * @throws NullPointerException if {@code toElement} is null * @throws IllegalArgumentException {@inheritDoc} */ - public NavigableSet headSet(E toElement, boolean inclusive) { + public @PolyGrowShrink @PolyNonEmpty NavigableSet headSet(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this, E toElement, boolean inclusive) { return new ConcurrentSkipListSet(m.headMap(toElement, inclusive)); } @@ -456,7 +458,7 @@ public NavigableSet headSet(E toElement, boolean inclusive) { * @throws NullPointerException if {@code fromElement} is null * @throws IllegalArgumentException {@inheritDoc} */ - public NavigableSet tailSet(E fromElement, boolean inclusive) { + public @PolyGrowShrink @PolyNonEmpty NavigableSet tailSet(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this, E fromElement, boolean inclusive) { return new ConcurrentSkipListSet(m.tailMap(fromElement, inclusive)); } @@ -466,7 +468,7 @@ public NavigableSet tailSet(E fromElement, boolean inclusive) { * {@code toElement} is null * @throws IllegalArgumentException {@inheritDoc} */ - public NavigableSet subSet(E fromElement, E toElement) { + public @PolyGrowShrink @PolyNonEmpty NavigableSet subSet(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this, E fromElement, E toElement) { return subSet(fromElement, true, toElement, false); } @@ -475,7 +477,7 @@ public NavigableSet subSet(E fromElement, E toElement) { * @throws NullPointerException if {@code toElement} is null * @throws IllegalArgumentException {@inheritDoc} */ - public NavigableSet headSet(E toElement) { + public @PolyGrowShrink @PolyNonEmpty NavigableSet headSet(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this, E toElement) { return headSet(toElement, false); } @@ -484,7 +486,7 @@ public NavigableSet headSet(E toElement) { * @throws NullPointerException if {@code fromElement} is null * @throws IllegalArgumentException {@inheritDoc} */ - public NavigableSet tailSet(E fromElement) { + public @PolyGrowShrink @PolyNonEmpty NavigableSet tailSet(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this, E fromElement) { return tailSet(fromElement, true); } @@ -500,7 +502,7 @@ public NavigableSet tailSet(E fromElement) { * * @return a reverse order view of this set */ - public NavigableSet descendingSet() { + public @PolyGrowShrink @PolyNonEmpty NavigableSet descendingSet(@PolyGrowShrink @PolyNonEmpty ConcurrentSkipListSet this) { return new ConcurrentSkipListSet(m.descendingMap()); } diff --git a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java index cec8b6d32e2..9ef72dfb449 100644 --- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java +++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java @@ -34,10 +34,13 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -490,7 +493,7 @@ public void add(int index, E element) { * * @throws IndexOutOfBoundsException {@inheritDoc} */ - public E remove(int index) { + public E remove(@GuardSatisfied @Shrinkable CopyOnWriteArrayList this, int index) { synchronized (lock) { Object[] es = getArray(); int len = es.length; @@ -522,7 +525,7 @@ public E remove(int index) { * @param o element to be removed from this list, if present * @return {@code true} if this list contained the specified element */ - public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@Shrinkable CopyOnWriteArrayList this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { Object[] snapshot = getArray(); int index = indexOfRange(o, snapshot, 0, snapshot.length); return index >= 0 && remove(o, snapshot, index); @@ -532,7 +535,7 @@ public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { * A version of remove(Object) using the strong hint that given * recent snapshot contains o at the given index. */ - private boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o, Object[] snapshot, int index) { + private boolean remove(@Shrinkable CopyOnWriteArrayList this, @GuardSatisfied @Nullable @UnknownSignedness Object o, Object[] snapshot, int index) { synchronized (lock) { Object[] current = getArray(); int len = current.length; @@ -575,7 +578,7 @@ private boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o, Ob * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range * ({@code fromIndex < 0 || toIndex > size() || toIndex < fromIndex}) */ - void removeRange(int fromIndex, int toIndex) { + void removeRange(@GuardSatisfied @Shrinkable CopyOnWriteArrayList this, int fromIndex, int toIndex) { synchronized (lock) { Object[] es = getArray(); int len = es.length; @@ -670,7 +673,7 @@ public boolean containsAll(Collection c) { * or if the specified collection is null * @see #remove(Object) */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable CopyOnWriteArrayList this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -691,7 +694,7 @@ public boolean removeAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable CopyOnWriteArrayList this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } @@ -738,7 +741,7 @@ public int addAllAbsent(Collection c) { * Removes all of the elements from this list. * The list will be empty after this call returns. */ - public void clear() { + public void clear(@GuardSatisfied @Shrinkable CopyOnWriteArrayList this) { synchronized (lock) { setArray(new Object[0]); } @@ -831,7 +834,7 @@ public void forEach(Consumer action) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable CopyOnWriteArrayList this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -1042,7 +1045,7 @@ public int hashCode() { * * @return an iterator over the elements in this list in proper sequence */ - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty CopyOnWriteArrayList this) { return new COWIterator(getArray(), 0); } @@ -1054,7 +1057,7 @@ public Iterator iterator() { * traversing the iterator. The iterator does NOT support the * {@code remove}, {@code set} or {@code add} methods. */ - public ListIterator listIterator() { + public @PolyGrowShrink @PolyNonEmpty ListIterator listIterator(@PolyGrowShrink @PolyNonEmpty CopyOnWriteArrayList this) { return new COWIterator(getArray(), 0); } @@ -1068,7 +1071,7 @@ public ListIterator listIterator() { * * @throws IndexOutOfBoundsException {@inheritDoc} */ - public ListIterator listIterator(int index) { + public @PolyGrowShrink ListIterator listIterator(@PolyGrowShrink CopyOnWriteArrayList this, int index) { Object[] es = getArray(); int len = es.length; if (index < 0 || index > len) @@ -1195,7 +1198,7 @@ public void forEachRemaining(Consumer action) { * @return a view of the specified range within this list * @throws IndexOutOfBoundsException {@inheritDoc} */ - public List subList(int fromIndex, int toIndex) { + public @PolyGrowShrink List subList(@PolyGrowShrink CopyOnWriteArrayList this, int fromIndex, int toIndex) { synchronized (lock) { Object[] es = getArray(); int len = es.length; diff --git a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java index 017289436ca..b0078296d26 100644 --- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java +++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java @@ -35,10 +35,12 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -405,7 +407,7 @@ public boolean retainAll(Collection iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty CopyOnWriteArraySet this) { return al.iterator(); } diff --git a/src/java.base/share/classes/java/util/concurrent/DelayQueue.java b/src/java.base/share/classes/java/util/concurrent/DelayQueue.java index dd0b7f4b2b1..464ef25510b 100644 --- a/src/java.base/share/classes/java/util/concurrent/DelayQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/DelayQueue.java @@ -48,6 +48,10 @@ import org.checkerframework.framework.qual.AnnotatedFor; import static java.util.concurrent.TimeUnit.NANOSECONDS; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.index.qual.Shrinkable; import java.util.AbstractQueue; import java.util.Collection; import java.util.Iterator; @@ -200,7 +204,7 @@ public boolean offer(E e, long timeout, TimeUnit unit) { * @return the head of this queue, or {@code null} if this * queue has no elements with an expired delay */ - public @Nullable E poll() { + public @Nullable E poll(@GuardSatisfied @Shrinkable DelayQueue this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -220,7 +224,7 @@ public boolean offer(E e, long timeout, TimeUnit unit) { * @return the head of this queue * @throws InterruptedException {@inheritDoc} */ - public E take() throws InterruptedException { + public E take(@GuardSatisfied @Shrinkable DelayQueue this) throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { @@ -264,7 +268,7 @@ public E take() throws InterruptedException { * an expired delay becomes available * @throws InterruptedException {@inheritDoc} */ - public @Nullable E poll(long timeout, TimeUnit unit) throws InterruptedException { + public @Nullable E poll(@GuardSatisfied @Shrinkable DelayQueue this, long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); @@ -343,7 +347,7 @@ public int size() { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c) { + public int drainTo(@GuardSatisfied @Shrinkable DelayQueue this, Collection c) { return drainTo(c, Integer.MAX_VALUE); } @@ -353,7 +357,7 @@ public int drainTo(Collection c) { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c, int maxElements) { + public int drainTo(@GuardSatisfied @Shrinkable DelayQueue this, Collection c, int maxElements) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); @@ -383,7 +387,7 @@ public int drainTo(Collection c, int maxElements) { * Elements with an unexpired delay are not waited for; they are * simply discarded from the queue. */ - public void clear() { + public void clear(@GuardSatisfied @Shrinkable DelayQueue this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -477,7 +481,7 @@ public int remainingCapacity() { * Removes a single instance of the specified element from this * queue, if it is present, whether or not it has expired. */ - public boolean remove(@UnknownSignedness Object o) { + public boolean remove(@Shrinkable DelayQueue this, @UnknownSignedness Object o) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -516,7 +520,7 @@ void removeEQ(Object o) { * @return an iterator over the elements in this queue */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty DelayQueue this) { return new Itr(toArray()); } diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java index 732b70aa9d2..c4479427497 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java @@ -35,10 +35,13 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -257,7 +260,7 @@ private boolean linkLast(Node node) { /** * Removes and returns first element, or null if empty. */ - private E unlinkFirst() { + private E unlinkFirst(@Shrinkable LinkedBlockingDeque this) { // assert lock.isHeldByCurrentThread(); Node f = first; if (f == null) @@ -279,7 +282,7 @@ private E unlinkFirst() { /** * Removes and returns last element, or null if empty. */ - private E unlinkLast() { + private E unlinkLast(@Shrinkable LinkedBlockingDeque this) { // assert lock.isHeldByCurrentThread(); Node l = last; if (l == null) @@ -301,7 +304,7 @@ private E unlinkLast() { /** * Unlinks x. */ - void unlink(Node x) { + void unlink(@Shrinkable LinkedBlockingDeque this, Node x) { // assert lock.isHeldByCurrentThread(); // assert x.item != null; Node p = x.prev; @@ -454,7 +457,7 @@ public boolean offerLast(E e, long timeout, TimeUnit unit) /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeFirst(@NonEmpty LinkedBlockingDeque this) { + public E removeFirst(@GuardSatisfied @NonEmpty @Shrinkable LinkedBlockingDeque this) { E x = pollFirst(); if (x == null) throw new NoSuchElementException(); return x; @@ -463,13 +466,13 @@ public E removeFirst(@NonEmpty LinkedBlockingDeque this) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeLast(@NonEmpty LinkedBlockingDeque this) { + public E removeLast(@GuardSatisfied @NonEmpty @Shrinkable LinkedBlockingDeque this) { E x = pollLast(); if (x == null) throw new NoSuchElementException(); return x; } - public @Nullable E pollFirst() { + public @Nullable E pollFirst(@GuardSatisfied @Shrinkable LinkedBlockingDeque this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -479,7 +482,7 @@ public E removeLast(@NonEmpty LinkedBlockingDeque this) { } } - public @Nullable E pollLast() { + public @Nullable E pollLast(@GuardSatisfied @Shrinkable LinkedBlockingDeque this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -489,7 +492,7 @@ public E removeLast(@NonEmpty LinkedBlockingDeque this) { } } - public E takeFirst() throws InterruptedException { + public E takeFirst(@GuardSatisfied @Shrinkable LinkedBlockingDeque this) throws InterruptedException { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -502,7 +505,7 @@ public E takeFirst() throws InterruptedException { } } - public E takeLast() throws InterruptedException { + public E takeLast(@GuardSatisfied @Shrinkable LinkedBlockingDeque this) throws InterruptedException { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -515,7 +518,7 @@ public E takeLast() throws InterruptedException { } } - public @Nullable E pollFirst(long timeout, TimeUnit unit) + public @Nullable E pollFirst(@GuardSatisfied @Shrinkable LinkedBlockingDeque this, long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; @@ -533,7 +536,7 @@ public E takeLast() throws InterruptedException { } } - public @Nullable E pollLast(long timeout, TimeUnit unit) + public @Nullable E pollLast(@GuardSatisfied @Shrinkable LinkedBlockingDeque this, long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; @@ -591,7 +594,7 @@ public E getLast(@NonEmpty LinkedBlockingDeque this) { } } - public boolean removeFirstOccurrence(Object o) { + public boolean removeFirstOccurrence(@Shrinkable LinkedBlockingDeque this, Object o) { if (o == null) return false; final ReentrantLock lock = this.lock; lock.lock(); @@ -608,7 +611,7 @@ public boolean removeFirstOccurrence(Object o) { } } - public boolean removeLastOccurrence(Object o) { + public boolean removeLastOccurrence(@Shrinkable LinkedBlockingDeque this, Object o) { if (o == null) return false; final ReentrantLock lock = this.lock; lock.lock(); @@ -677,19 +680,19 @@ public boolean offer(E e, long timeout, TimeUnit unit) * @return the head of the queue represented by this deque * @throws NoSuchElementException if this deque is empty */ - public E remove(@NonEmpty LinkedBlockingDeque this) { + public E remove(@GuardSatisfied @NonEmpty @Shrinkable LinkedBlockingDeque this) { return removeFirst(); } - public @Nullable E poll() { + public @Nullable E poll(@GuardSatisfied @Shrinkable LinkedBlockingDeque this) { return pollFirst(); } - public E take() throws InterruptedException { + public E take(@GuardSatisfied @Shrinkable LinkedBlockingDeque this) throws InterruptedException { return takeFirst(); } - public @Nullable E poll(long timeout, TimeUnit unit) throws InterruptedException { + public @Nullable E poll(@GuardSatisfied @Shrinkable LinkedBlockingDeque this, long timeout, TimeUnit unit) throws InterruptedException { return pollFirst(timeout, unit); } @@ -739,7 +742,7 @@ public int remainingCapacity() { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c) { + public int drainTo(@GuardSatisfied @Shrinkable LinkedBlockingDeque this, Collection c) { return drainTo(c, Integer.MAX_VALUE); } @@ -749,7 +752,7 @@ public int drainTo(Collection c) { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c, int maxElements) { + public int drainTo(@GuardSatisfied @Shrinkable LinkedBlockingDeque this, Collection c, int maxElements) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); @@ -782,7 +785,7 @@ public void push(E e) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E pop(@NonEmpty LinkedBlockingDeque this) { + public E pop(@GuardSatisfied @NonEmpty @Shrinkable LinkedBlockingDeque this) { return removeFirst(); } @@ -802,7 +805,7 @@ public E pop(@NonEmpty LinkedBlockingDeque this) { * @param o element to be removed from this deque, if present * @return {@code true} if this deque changed as a result of the call */ - public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@Shrinkable LinkedBlockingDeque this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { return removeFirstOccurrence(o); } @@ -997,7 +1000,7 @@ public String toString() { * Atomically removes all of the elements from this deque. * The deque will be empty after this call returns. */ - public void clear() { + public void clear(@GuardSatisfied @Shrinkable LinkedBlockingDeque this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -1037,7 +1040,7 @@ Node succ(Node p) { * * @return an iterator over the elements in this deque in proper sequence */ - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty LinkedBlockingDeque this) { return new Itr(); } @@ -1051,7 +1054,7 @@ public Iterator iterator() { * * @return an iterator over the elements in this deque in reverse order */ - public Iterator descendingIterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator descendingIterator(@PolyGrowShrink @PolyNonEmpty LinkedBlockingDeque this) { return new DescendingItr(); } @@ -1352,7 +1355,7 @@ void forEachFrom(Consumer action, Node p) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable LinkedBlockingDeque this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -1360,7 +1363,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable LinkedBlockingDeque this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1368,7 +1371,7 @@ public boolean removeAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable LinkedBlockingDeque this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java index a24e36f1f49..c260d22481a 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java @@ -35,9 +35,12 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -437,7 +440,7 @@ public boolean offer(E e) { return true; } - public E take() throws InterruptedException { + public E take(@GuardSatisfied @Shrinkable LinkedBlockingQueue this) throws InterruptedException { final E x; final int c; final AtomicInteger count = this.count; @@ -459,7 +462,7 @@ public E take() throws InterruptedException { return x; } - public @Nullable E poll(long timeout, TimeUnit unit) throws InterruptedException { + public @Nullable E poll(@GuardSatisfied @Shrinkable LinkedBlockingQueue this, long timeout, TimeUnit unit) throws InterruptedException { final E x; final int c; long nanos = unit.toNanos(timeout); @@ -484,7 +487,7 @@ public E take() throws InterruptedException { return x; } - public @Nullable E poll() { + public @Nullable E poll(@GuardSatisfied @Shrinkable LinkedBlockingQueue this) { final AtomicInteger count = this.count; if (count.get() == 0) return null; @@ -548,7 +551,7 @@ void unlink(Node p, Node pred) { * @param o element to be removed from this queue, if present * @return {@code true} if this queue changed as a result of the call */ - public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@Shrinkable LinkedBlockingQueue this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o == null) return false; fullyLock(); try { @@ -679,7 +682,7 @@ public String toString() { * Atomically removes all of the elements from this queue. * The queue will be empty after this call returns. */ - public void clear() { + public void clear(@GuardSatisfied @Shrinkable LinkedBlockingQueue this) { fullyLock(); try { for (Node p, h = head; (p = h.next) != null; h = p) { @@ -701,7 +704,7 @@ public void clear() { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c) { + public int drainTo(@GuardSatisfied @Shrinkable LinkedBlockingQueue this, Collection c) { return drainTo(c, Integer.MAX_VALUE); } @@ -711,7 +714,7 @@ public int drainTo(Collection c) { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c, int maxElements) { + public int drainTo(@GuardSatisfied @Shrinkable LinkedBlockingQueue this, Collection c, int maxElements) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); @@ -771,7 +774,7 @@ Node succ(Node p) { * * @return an iterator over the elements in this queue in proper sequence */ - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty LinkedBlockingQueue this) { return new Itr(); } @@ -1035,7 +1038,7 @@ void forEachFrom(Consumer action, Node p) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable LinkedBlockingQueue this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -1043,7 +1046,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable LinkedBlockingQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1051,7 +1054,7 @@ public boolean removeAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable LinkedBlockingQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java b/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java index 0011eb385c5..458eca65998 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java @@ -35,10 +35,13 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -1253,7 +1256,7 @@ public boolean add(E e) { * * @throws NullPointerException if the specified element is null */ - public boolean tryTransfer(E e) { + public boolean tryTransfer(@GuardSatisfied @Shrinkable LinkedTransferQueue this, E e) { return xfer(e, true, NOW, 0L) == null; } @@ -1268,7 +1271,7 @@ public boolean tryTransfer(E e) { * * @throws NullPointerException if the specified element is null */ - public void transfer(E e) throws InterruptedException { + public void transfer(@GuardSatisfied @Shrinkable LinkedTransferQueue this, E e) throws InterruptedException { if (xfer(e, true, SYNC, 0L) != null) { Thread.interrupted(); // failure possible only due to interrupt throw new InterruptedException(); @@ -1289,7 +1292,7 @@ public void transfer(E e) throws InterruptedException { * * @throws NullPointerException if the specified element is null */ - public boolean tryTransfer(E e, long timeout, TimeUnit unit) + public boolean tryTransfer(@GuardSatisfied @Shrinkable LinkedTransferQueue this, E e, long timeout, TimeUnit unit) throws InterruptedException { if (xfer(e, true, TIMED, unit.toNanos(timeout)) == null) return true; @@ -1298,7 +1301,7 @@ public boolean tryTransfer(E e, long timeout, TimeUnit unit) throw new InterruptedException(); } - public E take() throws InterruptedException { + public E take(@GuardSatisfied @Shrinkable LinkedTransferQueue this) throws InterruptedException { E e = xfer(null, false, SYNC, 0L); if (e != null) return e; @@ -1306,14 +1309,14 @@ public E take() throws InterruptedException { throw new InterruptedException(); } - public @Nullable E poll(long timeout, TimeUnit unit) throws InterruptedException { + public @Nullable E poll(@GuardSatisfied @Shrinkable LinkedTransferQueue this, long timeout, TimeUnit unit) throws InterruptedException { E e = xfer(null, false, TIMED, unit.toNanos(timeout)); if (e != null || !Thread.interrupted()) return e; throw new InterruptedException(); } - public @Nullable E poll() { + public @Nullable E poll(@GuardSatisfied @Shrinkable LinkedTransferQueue this) { return xfer(null, false, NOW, 0L); } @@ -1321,7 +1324,7 @@ public E take() throws InterruptedException { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c) { + public int drainTo(@GuardSatisfied @Shrinkable LinkedTransferQueue this, Collection c) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); @@ -1335,7 +1338,7 @@ public int drainTo(Collection c) { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c, int maxElements) { + public int drainTo(@GuardSatisfied @Shrinkable LinkedTransferQueue this, Collection c, int maxElements) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); @@ -1354,7 +1357,7 @@ public int drainTo(Collection c, int maxElements) { * * @return an iterator over the elements in this queue in proper sequence */ - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty LinkedTransferQueue this) { return new Itr(); } @@ -1438,7 +1441,7 @@ public int getWaitingConsumerCount() { * @param o element to be removed from this queue, if present * @return {@code true} if this queue changed as a result of the call */ - public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@Shrinkable LinkedTransferQueue this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o == null) return false; restartFromHead: for (;;) { for (Node p = head, pred = null; p != null; ) { @@ -1558,7 +1561,7 @@ private void readObject(java.io.ObjectInputStream s) /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable LinkedTransferQueue this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -1566,7 +1569,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable LinkedTransferQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1574,12 +1577,12 @@ public boolean removeAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable LinkedTransferQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } - public void clear() { + public void clear(@GuardSatisfied @Shrinkable LinkedTransferQueue this) { bulkRemove(e -> true); } diff --git a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java index e6ca1ad852f..93fa3b5eb85 100644 --- a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java @@ -35,10 +35,13 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -530,7 +533,7 @@ public boolean offer(E e, long timeout, TimeUnit unit) { return offer(e); // never need to block } - public @Nullable E poll() { + public @Nullable E poll(@GuardSatisfied @Shrinkable PriorityBlockingQueue this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -540,7 +543,7 @@ public boolean offer(E e, long timeout, TimeUnit unit) { } } - public E take() throws InterruptedException { + public E take(@GuardSatisfied @Shrinkable PriorityBlockingQueue this) throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); E result; @@ -553,7 +556,7 @@ public E take() throws InterruptedException { return result; } - public @Nullable E poll(long timeout, TimeUnit unit) throws InterruptedException { + public @Nullable E poll(@GuardSatisfied @Shrinkable PriorityBlockingQueue this, long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); @@ -658,7 +661,7 @@ private void removeAt(int i) { * @param o element to be removed from this queue, if present * @return {@code true} if this queue changed as a result of the call */ - public boolean remove(@Nullable @UnknownSignedness Object o) { + public boolean remove(@Shrinkable PriorityBlockingQueue this, @Nullable @UnknownSignedness Object o) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -723,7 +726,7 @@ public String toString() { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c) { + public int drainTo(@GuardSatisfied @Shrinkable PriorityBlockingQueue this, Collection c) { return drainTo(c, Integer.MAX_VALUE); } @@ -733,7 +736,7 @@ public int drainTo(Collection c) { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c, int maxElements) { + public int drainTo(@GuardSatisfied @Shrinkable PriorityBlockingQueue this, Collection c, int maxElements) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); @@ -757,7 +760,7 @@ public int drainTo(Collection c, int maxElements) { * Atomically removes all of the elements from this queue. * The queue will be empty after this call returns. */ - public void clear() { + public void clear(@GuardSatisfied @Shrinkable PriorityBlockingQueue this) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -855,7 +858,7 @@ public void clear() { * * @return an iterator over the elements in this queue */ - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty PriorityBlockingQueue this) { return new Itr(toArray()); } @@ -1028,7 +1031,7 @@ public Spliterator spliterator() { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeIf(Predicate filter) { + public boolean removeIf(@Shrinkable PriorityBlockingQueue this, Predicate filter) { Objects.requireNonNull(filter); return bulkRemove(filter); } @@ -1036,7 +1039,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable PriorityBlockingQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1044,7 +1047,7 @@ public boolean removeAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable PriorityBlockingQueue this, Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } diff --git a/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java b/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java index 0f4e904297a..248b5255453 100644 --- a/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java @@ -36,8 +36,11 @@ package java.util.concurrent; +import org.checkerframework.checker.index.qual.PolyGrowShrink; +import org.checkerframework.checker.index.qual.Shrinkable; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.PolyNonEmpty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -894,7 +897,7 @@ public boolean offer(E e) { * @return the head of this queue * @throws InterruptedException {@inheritDoc} */ - public E take() throws InterruptedException { + public E take(@GuardSatisfied @Shrinkable SynchronousQueue this) throws InterruptedException { E e = transferer.transfer(null, false, 0); if (e != null) return e; @@ -911,7 +914,7 @@ public E take() throws InterruptedException { * specified waiting time elapses before an element is present * @throws InterruptedException {@inheritDoc} */ - public @Nullable E poll(long timeout, TimeUnit unit) throws InterruptedException { + public @Nullable E poll(@GuardSatisfied @Shrinkable SynchronousQueue this, long timeout, TimeUnit unit) throws InterruptedException { E e = transferer.transfer(null, true, unit.toNanos(timeout)); if (e != null || !Thread.interrupted()) return e; @@ -925,7 +928,7 @@ public E take() throws InterruptedException { * @return the head of this queue, or {@code null} if no * element is available */ - public @Nullable E poll() { + public @Nullable E poll(@GuardSatisfied @Shrinkable SynchronousQueue this) { return transferer.transfer(null, true, 0); } @@ -966,7 +969,7 @@ public int remainingCapacity() { * Does nothing. * A {@code SynchronousQueue} has no internal capacity. */ - public void clear() { + public void clear(@GuardSatisfied @Shrinkable SynchronousQueue this) { } /** @@ -989,7 +992,7 @@ public boolean contains(@GuardSatisfied @Nullable @UnknownSignedness Object o) { * @param o the element to remove * @return {@code false} */ - public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { + public boolean remove(@Shrinkable SynchronousQueue this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { return false; } @@ -1012,7 +1015,7 @@ public boolean containsAll(Collection c) { * @param c the collection * @return {@code false} */ - public boolean removeAll(Collection c) { + public boolean removeAll(@Shrinkable SynchronousQueue this, Collection c) { return false; } @@ -1023,7 +1026,7 @@ public boolean removeAll(Collection c) { * @param c the collection * @return {@code false} */ - public boolean retainAll(Collection c) { + public boolean retainAll(@GuardSatisfied @Shrinkable SynchronousQueue this, Collection c) { return false; } @@ -1046,7 +1049,7 @@ public boolean retainAll(Collection c) { * @return an empty iterator */ @SideEffectFree - public Iterator iterator() { + public @PolyGrowShrink @PolyNonEmpty Iterator iterator(@PolyGrowShrink @PolyNonEmpty SynchronousQueue this) { return Collections.emptyIterator(); } @@ -1100,7 +1103,7 @@ public String toString() { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c) { + public int drainTo(@GuardSatisfied @Shrinkable SynchronousQueue this, Collection c) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); @@ -1116,7 +1119,7 @@ public int drainTo(Collection c) { * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ - public int drainTo(Collection c, int maxElements) { + public int drainTo(@GuardSatisfied @Shrinkable SynchronousQueue this, Collection c, int maxElements) { Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/BottomGrowShrink.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/BottomGrowShrink.java new file mode 100644 index 00000000000..2df971a0a66 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/BottomGrowShrink.java @@ -0,0 +1,20 @@ +package org.checkerframework.checker.index.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * The bottom qualifier in the GrowShrink hierarchy. Programmers should rarely write this type. + * + * @checker_framework.manual #growonly-checker Grow-only Checker + * @checker_framework.manual #bottom-type the bottom type + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({GrowOnly.class, UncheckedShrinkable.class}) +public @interface BottomGrowShrink {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/GrowOnly.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/GrowOnly.java new file mode 100644 index 00000000000..61644656ca7 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/GrowOnly.java @@ -0,0 +1,21 @@ +package org.checkerframework.checker.index.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * An expression of type {@code @GrowOnly} may not be used to remove elements, e.g., by calling + * {@code remove()} or {@code clear()} on it. The underlying collection is guaranteed not to shrink + * via operations on aliases. + * + * @checker_framework.manual #growonly-checker Grow-only Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({UnshrinkableRef.class}) +public @interface GrowOnly {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/PolyGrowShrink.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/PolyGrowShrink.java new file mode 100644 index 00000000000..2f10e01b96e --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/PolyGrowShrink.java @@ -0,0 +1,20 @@ +package org.checkerframework.checker.index.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.PolymorphicQualifier; + +/** + * A polymorphic qualifier for @GrowOnly type system. + * + * @checker_framework.manual #index-checker Index Checker + * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@PolymorphicQualifier(UnshrinkableRef.class) +public @interface PolyGrowShrink {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/Shrinkable.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/Shrinkable.java new file mode 100644 index 00000000000..8bbe4ccbdda --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/Shrinkable.java @@ -0,0 +1,20 @@ +package org.checkerframework.checker.index.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * An expression of type {@code @Shrinkable} may be used to remove elements, e.g., by calling {@code + * remove()} or {@code clear()} on it. + * + * @checker_framework.manual #growonly-checker Grow-only Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({UnshrinkableRef.class}) +public @interface Shrinkable {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/UncheckedShrinkable.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/UncheckedShrinkable.java new file mode 100644 index 00000000000..cbd4acc669e --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/UncheckedShrinkable.java @@ -0,0 +1,28 @@ +package org.checkerframework.checker.index.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * An expression of type {@code @UncheckedShrinkable} may be used to remove elements, e.g., by + * calling {@code remove()} or {@code clear()} on it. + * + *

      The Index Checker does not issue warnings about possible {@code IndexOutOfBoundsException}s + * when the collection has type {@code UncheckedShrinkable}. + * + *

      Thus, {@code @UncheckedShrinkable} is combination of {@code @}{@link Shrinkable} and a warning + * suppression. It is particularly useful when first annotating a codebase, to temporarily suppress + * some warnings while focusing on others. + * + * @checker_framework.manual #index-checker Index Checker + * @checker_framework.manual #growonly-checker Grow-only Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({Shrinkable.class}) +public @interface UncheckedShrinkable {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/UnshrinkableRef.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/UnshrinkableRef.java new file mode 100644 index 00000000000..cb05e97a548 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/UnshrinkableRef.java @@ -0,0 +1,25 @@ +package org.checkerframework.checker.index.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.InvisibleQualifier; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * An expression of type {@code @UnshrinkableRef} may not be used to remove elements, e.g., by + * calling {@code remove()} or {@code clear()} on it. The collection might be shrunk by some other + * reference that aliases the expression of type {@code @UnshrinkableRef}. + * + * @checker_framework.manual #growonly-checker Grow-only Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({}) +@DefaultQualifierInHierarchy +@InvisibleQualifier +public @interface UnshrinkableRef {} From 7f164b03e18f796f408892ea8e8fc63e7e03f8a3 Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Thu, 1 Oct 2026 07:16:08 -0400 Subject: [PATCH 62/82] Sync the qualifier copies with the Checker Framework The qualifier files in this repository are identical to the files in the EISOP Checker Framework, which are formatted in the AOSP style and contain the changes of the typetools 3.50.0 release. Take the files from there, including the new GrowOnly and shrink qualifiers. Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01GW8C4XvQcY7RQkVAqStDB6 --- .../checker/index/qual/BottomGrowShrink.java | 3 ++- .../org/checkerframework/checker/index/qual/GrowOnly.java | 3 ++- .../checker/index/qual/PolyGrowShrink.java | 3 ++- .../checkerframework/checker/index/qual/Shrinkable.java | 3 ++- .../checker/index/qual/UncheckedShrinkable.java | 3 ++- .../checker/index/qual/UnshrinkableRef.java | 7 ++++--- 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/BottomGrowShrink.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/BottomGrowShrink.java index 2df971a0a66..e04c5819148 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/BottomGrowShrink.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/BottomGrowShrink.java @@ -1,11 +1,12 @@ package org.checkerframework.checker.index.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * The bottom qualifier in the GrowShrink hierarchy. Programmers should rarely write this type. diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/GrowOnly.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/GrowOnly.java index 61644656ca7..a773a65f878 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/GrowOnly.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/GrowOnly.java @@ -1,11 +1,12 @@ package org.checkerframework.checker.index.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * An expression of type {@code @GrowOnly} may not be used to remove elements, e.g., by calling diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/PolyGrowShrink.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/PolyGrowShrink.java index 2f10e01b96e..29e741f517c 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/PolyGrowShrink.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/PolyGrowShrink.java @@ -1,11 +1,12 @@ package org.checkerframework.checker.index.qual; +import org.checkerframework.framework.qual.PolymorphicQualifier; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.PolymorphicQualifier; /** * A polymorphic qualifier for @GrowOnly type system. diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/Shrinkable.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/Shrinkable.java index 8bbe4ccbdda..4076f3dd1e6 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/Shrinkable.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/Shrinkable.java @@ -1,11 +1,12 @@ package org.checkerframework.checker.index.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * An expression of type {@code @Shrinkable} may be used to remove elements, e.g., by calling {@code diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/UncheckedShrinkable.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/UncheckedShrinkable.java index cbd4acc669e..9d15582ea46 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/UncheckedShrinkable.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/UncheckedShrinkable.java @@ -1,11 +1,12 @@ package org.checkerframework.checker.index.qual; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.SubtypeOf; /** * An expression of type {@code @UncheckedShrinkable} may be used to remove elements, e.g., by diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/UnshrinkableRef.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/UnshrinkableRef.java index cb05e97a548..0dee24871c1 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/UnshrinkableRef.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/UnshrinkableRef.java @@ -1,13 +1,14 @@ package org.checkerframework.checker.index.qual; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.InvisibleQualifier; +import org.checkerframework.framework.qual.SubtypeOf; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; -import org.checkerframework.framework.qual.InvisibleQualifier; -import org.checkerframework.framework.qual.SubtypeOf; /** * An expression of type {@code @UnshrinkableRef} may not be used to remove elements, e.g., by From 0c5a5c0fde43d19ac50cb949f83da1b1a3e4cc91 Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Thu, 1 Oct 2026 15:20:10 -0400 Subject: [PATCH 63/82] Sync the qualifier copies with the Checker Framework (#154) Co-authored-by: Claude Sonnet 5.5 --- .../checker/index/qual/BottomGrowShrink.java | 3 ++- .../checkerframework/checker/index/qual/GrowOnly.java | 4 ++-- .../checker/index/qual/PolyGrowShrink.java | 2 ++ .../checkerframework/checker/index/qual/Shrinkable.java | 4 ++-- .../checker/index/qual/UncheckedShrinkable.java | 3 ++- .../checker/index/qual/UnshrinkableRef.java | 4 ++-- .../checker/nonempty/qual/EnsuresNonEmpty.java | 3 ++- .../checker/nonempty/qual/EnsuresNonEmptyIf.java | 3 ++- .../checkerframework/checker/nonempty/qual/NonEmpty.java | 4 ++-- .../checker/nonempty/qual/PolyNonEmpty.java | 3 ++- .../checker/nonempty/qual/RequiresNonEmpty.java | 9 +++++++-- .../checker/nonempty/qual/UnknownNonEmpty.java | 4 ++-- .../org/checkerframework/dataflow/qual/AssertMethod.java | 2 +- 13 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/BottomGrowShrink.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/BottomGrowShrink.java index e04c5819148..95f336c5e09 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/BottomGrowShrink.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/BottomGrowShrink.java @@ -11,9 +11,10 @@ /** * The bottom qualifier in the GrowShrink hierarchy. Programmers should rarely write this type. * - * @checker_framework.manual #growonly-checker Grow-only Checker * @checker_framework.manual #bottom-type the bottom type */ +// Reinstate when lists are supported: +// * @checker_framework.manual #growonly-checker Grow-only Checker @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/GrowOnly.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/GrowOnly.java index a773a65f878..3648a73d1c7 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/GrowOnly.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/GrowOnly.java @@ -12,9 +12,9 @@ * An expression of type {@code @GrowOnly} may not be used to remove elements, e.g., by calling * {@code remove()} or {@code clear()} on it. The underlying collection is guaranteed not to shrink * via operations on aliases. - * - * @checker_framework.manual #growonly-checker Grow-only Checker */ +// Reinstate when lists are supported: +// * @checker_framework.manual #growonly-checker Grow-only Checker @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/PolyGrowShrink.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/PolyGrowShrink.java index 29e741f517c..03f151a914d 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/PolyGrowShrink.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/PolyGrowShrink.java @@ -14,6 +14,8 @@ * @checker_framework.manual #index-checker Index Checker * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism */ +// Reinstate when lists are supported: +// * @checker_framework.manual #growonly-checker Grow-only Checker @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/Shrinkable.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/Shrinkable.java index 4076f3dd1e6..44aa707b816 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/Shrinkable.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/Shrinkable.java @@ -11,9 +11,9 @@ /** * An expression of type {@code @Shrinkable} may be used to remove elements, e.g., by calling {@code * remove()} or {@code clear()} on it. - * - * @checker_framework.manual #growonly-checker Grow-only Checker */ +// Reinstate when lists are supported: +// * @checker_framework.manual #growonly-checker Grow-only Checker @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/UncheckedShrinkable.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/UncheckedShrinkable.java index 9d15582ea46..559cfc410dc 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/UncheckedShrinkable.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/UncheckedShrinkable.java @@ -20,8 +20,9 @@ * some warnings while focusing on others. * * @checker_framework.manual #index-checker Index Checker - * @checker_framework.manual #growonly-checker Grow-only Checker */ +// Reinstate when lists are supported: +// * @checker_framework.manual #growonly-checker Grow-only Checker @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) diff --git a/src/java.base/share/classes/org/checkerframework/checker/index/qual/UnshrinkableRef.java b/src/java.base/share/classes/org/checkerframework/checker/index/qual/UnshrinkableRef.java index 0dee24871c1..027507ebd47 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/index/qual/UnshrinkableRef.java +++ b/src/java.base/share/classes/org/checkerframework/checker/index/qual/UnshrinkableRef.java @@ -14,9 +14,9 @@ * An expression of type {@code @UnshrinkableRef} may not be used to remove elements, e.g., by * calling {@code remove()} or {@code clear()} on it. The collection might be shrunk by some other * reference that aliases the expression of type {@code @UnshrinkableRef}. - * - * @checker_framework.manual #growonly-checker Grow-only Checker */ +// Reinstate when lists are supported: +// * @checker_framework.manual #growonly-checker Grow-only Checker @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) diff --git a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmpty.java b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmpty.java index 125b529e15e..17993d6c3e6 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmpty.java +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmpty.java @@ -36,8 +36,9 @@ * * @see NonEmpty * @see org.checkerframework.checker.nonempty.NonEmptyChecker - * @checker_framework.manual #non-empty-checker Non-Empty Checker */ +// Reinstate when the Non-Empty Checker is publicized. +// * @checker_framework.manual #non-empty-checker Non-Empty Checker @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) @PostconditionAnnotation(qualifier = NonEmpty.class) diff --git a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmptyIf.java b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmptyIf.java index 07351e63bdc..83600e58e00 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmptyIf.java +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmptyIf.java @@ -45,8 +45,9 @@ * * @see NonEmpty * @see EnsuresNonEmpty - * @checker_framework.manual #non-empty-checker Non-Empty Checker */ +// Reinstate when the Non-Empty Checker is publicized. +// * @checker_framework.manual #non-empty-checker Non-Empty Checker @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) diff --git a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/NonEmpty.java b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/NonEmpty.java index aca1d5ff95b..cd340f2c163 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/NonEmpty.java +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/NonEmpty.java @@ -12,9 +12,9 @@ * The {@link java.util.Collection Collection}, {@link java.util.Iterator Iterator}, {@link Iterable * Iterable}, or {@link java.util.Map Map}, or {@link java.util.stream.Stream Stream} is definitely * non-empty. - * - * @checker_framework.manual #non-empty-checker Non-Empty Checker */ +// Reinstate when the Non-Empty Checker is publicized. +// * @checker_framework.manual #non-empty-checker Non-Empty Checker @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) diff --git a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/PolyNonEmpty.java b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/PolyNonEmpty.java index 792b8854f80..e70fd57eabd 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/PolyNonEmpty.java +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/PolyNonEmpty.java @@ -11,9 +11,10 @@ /** * A polymorphic qualifier for the Non-Empty type system. * - * @checker_framework.manual #non-empty-checker Non-Empty Checker * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism */ +// Reinstate when the Non-Empty Checker is publicized. +// * @checker_framework.manual #non-empty-checker Non-Empty Checker @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) diff --git a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/RequiresNonEmpty.java b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/RequiresNonEmpty.java index 799a11fa797..8840de35896 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/RequiresNonEmpty.java +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/RequiresNonEmpty.java @@ -4,6 +4,7 @@ import java.lang.annotation.Documented; import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -63,11 +64,12 @@ * This annotation should not be used for formal parameters (instead, give them a {@code @NonEmpty} * type). The {@code @RequiresNonEmpty} annotation is intended for non-parameter expressions, such * as field accesses or method calls. - * - * @checker_framework.manual #non-empty-checker Non-Empty Checker */ +// Reinstate when the Non-Empty Checker is publicized. +// * @checker_framework.manual #non-empty-checker Non-Empty Checker @Documented @Retention(RetentionPolicy.RUNTIME) +@Repeatable(RequiresNonEmpty.List.class) @Target({ElementType.METHOD, ElementType.PARAMETER}) @PreconditionAnnotation(qualifier = NonEmpty.class) public @interface RequiresNonEmpty { @@ -86,6 +88,9 @@ *

      Programmers generally do not need to write this. It is created by Java when a programmer * writes more than one {@link RequiresNonEmpty} annotation at the same location. */ + @Documented + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD, ElementType.PARAMETER}) @interface List { /** * Returns the repeatable annotations. diff --git a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/UnknownNonEmpty.java b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/UnknownNonEmpty.java index f34be666941..93b062e51e9 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/UnknownNonEmpty.java +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/UnknownNonEmpty.java @@ -13,9 +13,9 @@ * The {@link java.util.Collection Collection}, {@link java.util.Iterator Iterator}, {@link * java.lang.Iterable Iterable}, {@link java.util.Map Map}, or {@link java.util.stream.Stream * Stream} may or may not be empty. - * - * @checker_framework.manual #non-empty-checker Non-Empty Checker */ +// Reinstate when the Non-Empty Checker is publicized. +// * @checker_framework.manual #non-empty-checker Non-Empty Checker @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) diff --git a/src/java.base/share/classes/org/checkerframework/dataflow/qual/AssertMethod.java b/src/java.base/share/classes/org/checkerframework/dataflow/qual/AssertMethod.java index 6658f1b929d..ed29b6be34e 100644 --- a/src/java.base/share/classes/org/checkerframework/dataflow/qual/AssertMethod.java +++ b/src/java.base/share/classes/org/checkerframework/dataflow/qual/AssertMethod.java @@ -56,7 +56,7 @@ * Returns true if this method asserts that the boolean expression is false. * *

      For example, JUnit's Assertions.assertFalse(...) + * href="https://docs.junit.org/current/api/org.junit.jupiter.api/org/junit/jupiter/api/Assertions.html#assertFalse(boolean)">Assertions.assertFalse(...) * throws an exception if the first argument is false. So it is annotated as follows: * *

      {@code @AssertMethod(value = AssertionFailedError.class, isAssertFalse = true)
      
      From ffa5e5c081ba5057e492c409544457cbbfd48626 Mon Sep 17 00:00:00 2001
      From: Werner Dietl 
      Date: Thu, 1 Oct 2026 16:24:10 -0400
      Subject: [PATCH 64/82] Sync RequiresNonEmpty with the Checker Framework (#155)
      
      Co-authored-by: Claude Sonnet 5.5 
      ---
       .../checkerframework/checker/nonempty/qual/RequiresNonEmpty.java | 1 +
       1 file changed, 1 insertion(+)
      
      diff --git a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/RequiresNonEmpty.java b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/RequiresNonEmpty.java
      index 8840de35896..7deeeef4306 100644
      --- a/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/RequiresNonEmpty.java
      +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/RequiresNonEmpty.java
      @@ -91,6 +91,7 @@
           @Documented
           @Retention(RetentionPolicy.RUNTIME)
           @Target({ElementType.METHOD, ElementType.PARAMETER})
      +    @PreconditionAnnotation(qualifier = NonEmpty.class)
           @interface List {
               /**
                * Returns the repeatable annotations.
      
      From f940aee27d881598c2bf61d91bc7e0b9355dee6f Mon Sep 17 00:00:00 2001
      From: Werner Dietl 
      Date: Thu, 1 Oct 2026 18:37:19 -0400
      Subject: [PATCH 65/82] Sync EnsuresLockHeldIf with the Checker Framework
       3.52.0 release (#156)
      
      ---
       .../checkerframework/checker/lock/qual/EnsuresLockHeldIf.java | 4 ++--
       1 file changed, 2 insertions(+), 2 deletions(-)
      
      diff --git a/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeldIf.java b/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeldIf.java
      index fc11803def0..4b25377e10c 100644
      --- a/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeldIf.java
      +++ b/src/java.base/share/classes/org/checkerframework/checker/lock/qual/EnsuresLockHeldIf.java
      @@ -36,8 +36,8 @@
            * Returns Java expressions whose values are locks that are held after the method returns the
            * given result.
            *
      -     * @return Java expressions whose values are locks that are held after the method returns the
      -     *     given result
      +     * @return the Java expressions whose values are locks that are held after the method returns
      +     *     the given result
            * @see Syntax of
            *     Java expressions
            */
      
      From ce760870c3d480b753e98ba7b98b8e7b242be70e Mon Sep 17 00:00:00 2001
      From: Michael Ernst 
      Date: Thu, 13 Nov 2025 16:54:02 -0800
      Subject: [PATCH 66/82] Move `azure-pipelines.yml` into a subdirectory
      
      ---
       .azure/azure-pipelines.yml | 202 +++++++++++++++++++++++++++++++++++++
       1 file changed, 202 insertions(+)
       create mode 100644 .azure/azure-pipelines.yml
      
      diff --git a/.azure/azure-pipelines.yml b/.azure/azure-pipelines.yml
      new file mode 100644
      index 00000000000..a1cfd12516f
      --- /dev/null
      +++ b/.azure/azure-pipelines.yml
      @@ -0,0 +1,202 @@
      +variables:
      +  system.debug: true
      +
      +jobs:
      +
      +- job: build_jdk
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk17-plus:latest
      +  steps:
      +  - bash: |
      +      whoami
      +      git config --get remote.origin.url
      +      pwd
      +      ls -al
      +      env | sort
      +    displayName: show environment
      +  - bash: pwd && ls && bash ./configure --with-jtreg=/usr/share/jtreg --disable-warnings-as-errors
      +    displayName: configure
      +  - bash: make jdk
      +    timeoutInMinutes: 90
      +    displayName: make jdk
      +  ## This works only after `make images`
      +  # - bash: build/*/images/jdk/bin/java -version
      +  #   displayName: version
      +  ## Don't run tests, which pass only with old version of tools (compilers, etc.).
      +  # - bash: make -C /jdk run-test-tier1
      +  #   displayName: make run-test-tier1
      +
      +- job: build_jdk17u
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk17-plus:latest
      +  timeoutInMinutes: 0
      +  steps:
      +  - bash: |
      +      whoami
      +      git config --get remote.origin.url
      +      pwd
      +      ls -al
      +      env | sort
      +    displayName: show environment
      +  - bash: |
      +      set -ex
      +      if [ -d /tmp/$USER/git-scripts ]; \
      +        then git -C /tmp/$USER/git-scripts pull -q > /dev/null 2>&1 ; \
      +        else mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git ; \
      +      fi
      +    displayName: git-scripts
      +  - bash: |
      +      set -ex
      +      if [ -d /tmp/$USER/plume-scripts ]; \
      +        then git -C /tmp/$USER/plume-scripts pull -q > /dev/null 2>&1 ; \
      +        else mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/plume-scripts.git ; \
      +      fi
      +    displayName: plume-scripts
      +  # This creates ../jdk17u .
      +  # If the depth is too small, the merge will fail.  However, we cannot use "--filter=blob:none"
      +  # because that leads to "fatal: remote error: filter 'combine' not supported".
      +  - bash: |
      +      set -ex
      +      pwd
      +      ls -al .. || true
      +      ls -al ../jdk17u || true
      +      df .
      +      /tmp/$USER/git-scripts/git-clone-related typetools jdk17u ../jdk17u --depth 999
      +      git config --global user.email "you@example.com"
      +      git config --global user.name "Your Name"
      +      git config --global core.longpaths true
      +      git config --global core.protectNTFS false
      +      cd ../jdk17u && git status
      +      git diff --exit-code
      +      echo $?
      +    displayName: clone-related-jdk17u
      +  - bash: |
      +      set -ex
      +      git config --global user.email "you@example.com"
      +      git config --global user.name "Your Name"
      +      git config --global pull.ff true
      +      git config --global pull.rebase false
      +      git config --global core.longpaths true
      +      git config --global core.protectNTFS false
      +      eval `/tmp/$USER/plume-scripts/ci-info typetools`
      +      cd ../jdk17u && git status
      +      echo "About to run: git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH}"
      +      cd ../jdk17u && git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH} || (git --version && git show && git status && echo "Merge failed; see 'Pull request merge conflicts' at https://github.com/typetools/jdk/blob/master/README.md" && false)
      +    displayName: git merge
      +  - bash: cd ../jdk17u && export JT_HOME=/usr/share/jtreg && bash ./configure --with-jtreg --disable-warnings-as-errors
      +    displayName: configure
      +  - bash: cd ../jdk17u && make jdk
      +    displayName: make jdk
      +  ## This works only after `make images`
      +  # - bash: cd ../jdk17u && build/*/images/jdk/bin/java -version
      +  #   displayName: version
      +  # - bash: make -C /jdk17u run-test-tier1
      +  #   timeoutInMinutes: 0
      +  #   displayName: make run-test-tier1
      +  # - bash: make -C /jdk17u :test/jdk:tier1
      +  ## Temporarily comment out because of trouble finding junit and jasm
      +  # - bash: cd ../jdk17u && make run-test TEST="jtreg:test/jdk:tier1"
      +  #   timeoutInMinutes: 0
      +  #   displayName: make run-test
      +
      +- job: test_cftests_all_jdk11
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk11:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
      +# test-cftests-all.sh sometimes runs out of memory (under JDK 11 and 17), but running its component parts in sequence does not.
      +#   - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh)
      +#     displayName: test-cftests-all.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh)
      +    displayName: test-cftests-junit.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh)
      +    displayName: test-cftests-nonjunit.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh)
      +    displayName: test-cftests-inference.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh)
      +    displayName: test-typecheck.sh
      +## Here is how to create artifacts that can be downloaded.
      +#   - bash: (cd ../checker-framework/checker/build/jtregJdk11/ && tar -czvf all.tgz all)
      +#     condition: succeededOrFailed()
      +#     displayName: tar jtregJdk11/all
      +#   - publish: $(System.DefaultWorkingDirectory)/../checker-framework/checker/build/jtregJdk11/all.tgz
      +#     artifact: all.tgz
      +#     condition: failed()
      +#     displayName: publish all.tgz
      +
      +- job: test_cftests_all_jdk17
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk17:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
      +# test-cftests-all.sh sometimes runs out of memory (under JDK 11 and 17), but running its component parts in sequence does not.
      +#   - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh)
      +#     displayName: test-cftests-all.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh)
      +    displayName: test-cftests-junit.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh)
      +    displayName: test-cftests-nonjunit.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh)
      +    displayName: test-cftests-inference.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh)
      +    displayName: test-typecheck.sh
      +
      +- job: test_cftests_all_jdk21
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk21:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh)
      +    displayName: test-cftests-all.sh
      +
      +- job: test_daikon
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk17:latest
      +  timeoutInMinutes: 70
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-daikon.sh)
      +    displayName: test-daikon.sh
      +
      +- job: test_plume_lib
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk17:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-plume-lib.sh)
      +    displayName: test-plume-lib.sh
      
      From f26e07b5bcdb167dc8d33037de27793dcd160e91 Mon Sep 17 00:00:00 2001
      From: Michael Ernst 
      Date: Thu, 13 Nov 2025 19:04:38 -0800
      Subject: [PATCH 67/82] Generate `azure-pipelines.yml` via m4
      
      ---
       .azure/Makefile               |   9 ++
       .azure/azure-pipelines.yml    |  43 ++++++-
       .azure/azure-pipelines.yml.m4 | 121 ++++++++++++++++++++
       .azure/defs.m4                | 204 ++++++++++++++++++++++++++++++++++
       4 files changed, 372 insertions(+), 5 deletions(-)
       create mode 100644 .azure/Makefile
       create mode 100644 .azure/azure-pipelines.yml.m4
       create mode 100644 .azure/defs.m4
      
      diff --git a/.azure/Makefile b/.azure/Makefile
      new file mode 100644
      index 00000000000..8032512f759
      --- /dev/null
      +++ b/.azure/Makefile
      @@ -0,0 +1,9 @@
      +all default: azure-pipelines.yml
      +
      +%: %.m4 defs.m4
      +	@chmod -f +w $@ || true
      +	m4 $< > $@
      +	@chmod -w $@
      +
      +clean:
      +	rm -f azure-pipelines.yml
      diff --git a/.azure/azure-pipelines.yml b/.azure/azure-pipelines.yml
      index a1cfd12516f..fee7502c895 100644
      --- a/.azure/azure-pipelines.yml
      +++ b/.azure/azure-pipelines.yml
      @@ -1,3 +1,9 @@
      +# DO NOT EDIT azure-pipelines.yml.  Edit azure-pipelines.yml.m4 and defs.m4 instead.
      +
      +
      +
      +
      +
       variables:
         system.debug: true
       
      @@ -42,14 +48,14 @@ jobs:
           displayName: show environment
         - bash: |
             set -ex
      -      if [ -d /tmp/$USER/git-scripts ]; \
      +      if test -d /tmp/$USER/git-scripts ; \
               then git -C /tmp/$USER/git-scripts pull -q > /dev/null 2>&1 ; \
               else mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git ; \
             fi
           displayName: git-scripts
         - bash: |
             set -ex
      -      if [ -d /tmp/$USER/plume-scripts ]; \
      +      if test -d /tmp/$USER/plume-scripts ; \
               then git -C /tmp/$USER/plume-scripts pull -q > /dev/null 2>&1 ; \
               else mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/plume-scripts.git ; \
             fi
      @@ -80,7 +86,7 @@ jobs:
             git config --global pull.rebase false
             git config --global core.longpaths true
             git config --global core.protectNTFS false
      -      eval `/tmp/$USER/plume-scripts/ci-info typetools`
      +      eval $(/tmp/$USER/plume-scripts/ci-info typetools)
             cd ../jdk17u && git status
             echo "About to run: git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH}"
             cd ../jdk17u && git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH} || (git --version && git show && git status && echo "Merge failed; see 'Pull request merge conflicts' at https://github.com/typetools/jdk/blob/master/README.md" && false)
      @@ -156,6 +162,14 @@ jobs:
           displayName: test-cftests-inference.sh
         - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh)
           displayName: test-typecheck.sh
      +## Here is how to create artifacts that can be downloaded.
      +#   - bash: (cd ../checker-framework/checker/build/jtregJdk17/ && tar -czvf all.tgz all)
      +#     condition: succeededOrFailed()
      +#     displayName: tar jtregJdk17/all
      +#   - publish: $(System.DefaultWorkingDirectory)/../checker-framework/checker/build/jtregJdk17/all.tgz
      +#     artifact: all.tgz
      +#     condition: failed()
      +#     displayName: publish all.tgz
       
       - job: test_cftests_all_jdk21
         timeoutInMinutes: 120
      @@ -169,8 +183,26 @@ jobs:
           displayName: clone git-scripts
         - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
           displayName: clone checker-framework
      -  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh)
      -    displayName: test-cftests-all.sh
      +# test-cftests-all.sh sometimes runs out of memory (under JDK 11 and 17), but running its component parts in sequence does not.
      +#   - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh)
      +#     displayName: test-cftests-all.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh)
      +    displayName: test-cftests-junit.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh)
      +    displayName: test-cftests-nonjunit.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh)
      +    displayName: test-cftests-inference.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh)
      +    displayName: test-typecheck.sh
      +## Here is how to create artifacts that can be downloaded.
      +#   - bash: (cd ../checker-framework/checker/build/jtregJdk21/ && tar -czvf all.tgz all)
      +#     condition: succeededOrFailed()
      +#     displayName: tar jtregJdk21/all
      +#   - publish: $(System.DefaultWorkingDirectory)/../checker-framework/checker/build/jtregJdk21/all.tgz
      +#     artifact: all.tgz
      +#     condition: failed()
      +#     displayName: publish all.tgz
      +
       
       - job: test_daikon
         pool:
      @@ -200,3 +232,4 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-plume-lib.sh)
           displayName: test-plume-lib.sh
      +
      diff --git a/.azure/azure-pipelines.yml.m4 b/.azure/azure-pipelines.yml.m4
      new file mode 100644
      index 00000000000..c910f4fd917
      --- /dev/null
      +++ b/.azure/azure-pipelines.yml.m4
      @@ -0,0 +1,121 @@
      +# DO NOT EDIT azure-pipelines.yml.  Edit azure-pipelines.yml.m4 and defs.m4 instead.
      +
      +changequote
      +changequote(`[',`]')dnl
      +include([defs.m4])dnl
      +variables:
      +  system.debug: true
      +
      +jobs:
      +
      +- job: build_jdk
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk17-plus:latest
      +  steps:
      +  - bash: |
      +      whoami
      +      git config --get remote.origin.url
      +      pwd
      +      ls -al
      +      env | sort
      +    displayName: show environment
      +  - bash: pwd && ls && bash ./configure --with-jtreg=/usr/share/jtreg --disable-warnings-as-errors
      +    displayName: configure
      +  - bash: make jdk
      +    timeoutInMinutes: 90
      +    displayName: make jdk
      +  ## This works only after `make images`
      +  # - bash: build/*/images/jdk/bin/java -version
      +  #   displayName: version
      +  ## Don't run tests, which pass only with old version of tools (compilers, etc.).
      +  # - bash: make -C /jdk run-test-tier1
      +  #   displayName: make run-test-tier1
      +
      +- job: build_jdk17u
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk17-plus:latest
      +  timeoutInMinutes: 0
      +  steps:
      +  - bash: |
      +      whoami
      +      git config --get remote.origin.url
      +      pwd
      +      ls -al
      +      env | sort
      +    displayName: show environment
      +  - bash: |
      +      set -ex
      +      if test -d /tmp/$USER/git-scripts ; \
      +        then git -C /tmp/$USER/git-scripts pull -q > /dev/null 2>&1 ; \
      +        else mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git ; \
      +      fi
      +    displayName: git-scripts
      +  - bash: |
      +      set -ex
      +      if test -d /tmp/$USER/plume-scripts ; \
      +        then git -C /tmp/$USER/plume-scripts pull -q > /dev/null 2>&1 ; \
      +        else mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/plume-scripts.git ; \
      +      fi
      +    displayName: plume-scripts
      +  # This creates ../jdk17u .
      +  # If the depth is too small, the merge will fail.  However, we cannot use "--filter=blob:none"
      +  # because that leads to "fatal: remote error: filter 'combine' not supported".
      +  - bash: |
      +      set -ex
      +      pwd
      +      ls -al .. || true
      +      ls -al ../jdk17u || true
      +      df .
      +      /tmp/$USER/git-scripts/git-clone-related typetools jdk17u ../jdk17u --depth 999
      +      git config --global user.email "you@example.com"
      +      git config --global user.name "Your Name"
      +      git config --global core.longpaths true
      +      git config --global core.protectNTFS false
      +      cd ../jdk17u && git status
      +      git diff --exit-code
      +      echo $?
      +    displayName: clone-related-jdk17u
      +  - bash: |
      +      set -ex
      +      git config --global user.email "you@example.com"
      +      git config --global user.name "Your Name"
      +      git config --global pull.ff true
      +      git config --global pull.rebase false
      +      git config --global core.longpaths true
      +      git config --global core.protectNTFS false
      +      eval $(/tmp/$USER/plume-scripts/ci-info typetools)
      +      cd ../jdk17u && git status
      +      echo "About to run: git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH}"
      +      cd ../jdk17u && git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH} || (git --version && git show && git status && echo "Merge failed; see 'Pull request merge conflicts' at https://github.com/typetools/jdk/blob/master/README.md" && false)
      +    displayName: git merge
      +  - bash: cd ../jdk17u && export JT_HOME=/usr/share/jtreg && bash ./configure --with-jtreg --disable-warnings-as-errors
      +    displayName: configure
      +  - bash: cd ../jdk17u && make jdk
      +    displayName: make jdk
      +  ## This works only after `make images`
      +  # - bash: cd ../jdk17u && build/*/images/jdk/bin/java -version
      +  #   displayName: version
      +  # - bash: make -C /jdk17u run-test-tier1
      +  #   timeoutInMinutes: 0
      +  #   displayName: make run-test-tier1
      +  # - bash: make -C /jdk17u :test/jdk:tier1
      +  ## Temporarily comment out because of trouble finding junit and jasm
      +  # - bash: cd ../jdk17u && make run-test TEST="jtreg:test/jdk:tier1"
      +  #   timeoutInMinutes: 0
      +  #   displayName: make run-test
      +
      +cftests_all_job(11)
      +cftests_all_job(17)
      +cftests_all_job(21)
      +
      +daikon_job
      +
      +plume_lib_job(canary_version)
      +
      +ifelse([
      +Local Variables:
      +eval: (add-hook 'after-save-hook '(lambda () (run-command nil "make")) nil 'local)
      +end:
      +])dnl
      diff --git a/.azure/defs.m4 b/.azure/defs.m4
      new file mode 100644
      index 00000000000..28743248917
      --- /dev/null
      +++ b/.azure/defs.m4
      @@ -0,0 +1,204 @@
      +changequote
      +define(`LBRACKET',`[')dnl
      +define(`RBRACKET',`]')dnl
      +changequote(`[',`]')dnl
      +ifelse([The built-in "dnl" m4 macro means "discard to next line",])dnl
      +define([canary_os], [ubuntu])dnl
      +define([canary_version], [25])dnl
      +define([latest_version], [25])dnl
      +define([canary_test], [canary_os[]canary_version])dnl
      +define([docker_testing], [])dnl
      +ifelse([uncomment the next line to use the "testing" Docker images])dnl
      +ifelse([define([docker_testing], [-testing])])dnl
      +dnl
      +define([cftests_all_job], [dnl
      +- job: test_cftests_all_jdk$1
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk$1:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
      +# test-cftests-all.sh sometimes runs out of memory (under JDK 11 and 17), but running its component parts in sequence does not.
      +#   - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh)
      +#     displayName: test-cftests-all.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh)
      +    displayName: test-cftests-junit.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh)
      +    displayName: test-cftests-nonjunit.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh)
      +    displayName: test-cftests-inference.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh)
      +    displayName: test-typecheck.sh
      +## Here is how to create artifacts that can be downloaded.
      +#   - bash: (cd ../checker-framework/checker/build/jtregJdk$1/ && tar -czvf all.tgz all)
      +#     condition: succeededOrFailed()
      +#     displayName: tar jtregJdk$1/all
      +#   - publish: $(System.DefaultWorkingDirectory)/../checker-framework/checker/build/jtregJdk$1/all.tgz
      +#     artifact: all.tgz
      +#     condition: failed()
      +#     displayName: publish all.tgz
      +])
      +
      +define([junit_job], [dnl
      +  - job: junit_jdk$1
      +ifelse($1,canary_version,,[    dependsOn:
      +      - canary_jobs
      +      - junit_jdk[]canary_version
      +])dnl
      +    pool:
      +      vmImage: 'ubuntu-latest'
      +    container: mdernst/cf-ubuntu-jdk$1[]docker_testing:latest
      +    timeoutInMinutes: 70
      +    steps:
      +      - checkout: self
      +        fetchDepth: 25
      +      - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-cftests-junit.sh
      +        displayName: test-cftests-junit.sh])dnl
      +dnl
      +define([nonjunit_job], [dnl
      +  - job: nonjunit_jdk$1
      +ifelse($1,canary_version,,[    dependsOn:
      +      - canary_jobs
      +      - nonjunit_jdk[]canary_version
      +])dnl
      +    pool:
      +      vmImage: 'ubuntu-latest'
      +    container: mdernst/cf-ubuntu-jdk$1[]docker_testing:latest
      +    steps:
      +      - checkout: self
      +        fetchDepth: 25
      +      - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-cftests-nonjunit.sh
      +        displayName: test-cftests-nonjunit.sh])dnl
      +dnl
      +define([inference_job], [dnl
      +ifelse($1,canary_version,[dnl
      +  # Split into part1 and part2 only for the inference job that "canary_jobs" depends on.
      +  - job: inference_part1_jdk$1
      +    pool:
      +      vmImage: 'ubuntu-latest'
      +    container: mdernst/cf-ubuntu-jdk$1[]docker_testing:latest
      +    timeoutInMinutes: 90
      +    steps:
      +      - checkout: self
      +        fetchDepth: 25
      +      - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-cftests-inference-part1.sh
      +        displayName: test-cftests-inference-part1.sh
      +  - job: inference_part2_jdk$1
      +    pool:
      +      vmImage: 'ubuntu-latest'
      +    container: mdernst/cf-ubuntu-jdk$1[]docker_testing:latest
      +    timeoutInMinutes: 90
      +    steps:
      +      - checkout: self
      +        fetchDepth: 25
      +      - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-cftests-inference-part2.sh
      +        displayName: test-cftests-inference-part2.sh
      +],[dnl
      +  - job: inference_jdk$1
      +    dependsOn:
      +      - canary_jobs
      +      - inference_part1_jdk[]canary_version
      +      - inference_part2_jdk[]canary_version
      +    pool:
      +      vmImage: 'ubuntu-latest'
      +    container: mdernst/cf-ubuntu-jdk$1[]docker_testing:latest
      +    timeoutInMinutes: 90
      +    steps:
      +      - checkout: self
      +        fetchDepth: 25
      +      - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-cftests-inference.sh
      +        displayName: test-cftests-inference.sh
      +])dnl
      +])dnl
      +dnl
      +define([misc_job], [dnl
      +  - job: misc_jdk$1
      +ifelse($1,canary_version,,$1,latest_version,,[    dependsOn:
      +      - canary_jobs
      +      - misc_jdk[]canary_version
      +])dnl
      +    pool:
      +      vmImage: 'ubuntu-latest'
      +    container: mdernst/cf-ubuntu-jdk$1-plus[]docker_testing:latest
      +    steps:
      +      - checkout: self
      +        # Unlimited fetchDepth (0) for misc jobs, because of need to make contributors.tex.
      +        fetchDepth: 0
      +      - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-misc.sh
      +        displayName: test-misc.sh])dnl
      +dnl
      +define([typecheck_job], [dnl
      +ifelse($1,canary_version,[dnl
      +  - job: typecheck_part1_jdk$1
      +    pool:
      +      vmImage: 'ubuntu-latest'
      +    container: mdernst/cf-ubuntu-jdk$1[]docker_testing:latest
      +    steps:
      +      - checkout: self
      +        fetchDepth: 1000
      +      - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-typecheck-part1.sh
      +        displayName: test-typecheck-part1.sh
      +  - job: typecheck_part2_jdk$1
      +    pool:
      +      vmImage: 'ubuntu-latest'
      +    container: mdernst/cf-ubuntu-jdk$1[]docker_testing:latest
      +    steps:
      +      - checkout: self
      +        fetchDepth: 1000
      +      - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-typecheck-part2.sh
      +        displayName: test-typecheck-part2.sh], [dnl
      +  - job: typecheck_jdk$1
      +    dependsOn:
      +      - canary_jobs
      +      - typecheck_part1_jdk[]canary_version
      +      - typecheck_part2_jdk[]canary_version
      +    pool:
      +      vmImage: 'ubuntu-latest'
      +    container: mdernst/cf-ubuntu-jdk$1[]docker_testing:latest
      +    steps:
      +      - checkout: self
      +        fetchDepth: 1000
      +      - bash: export ORG_GRADLE_PROJECT_jdkTestVersion=$1 && ./checker/bin-devel/test-typecheck.sh
      +        displayName: test-typecheck.sh])])dnl
      +dnl
      +define([daikon_job], [dnl
      +- job: test_daikon
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk17:latest
      +  timeoutInMinutes: 70
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-daikon.sh)
      +    displayName: test-daikon.sh])dnl
      +dnl
      +define([plume_lib_job], [dnl
      +- job: test_plume_lib
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk17:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-plume-lib.sh)
      +    displayName: test-plume-lib.sh])dnl
      +ifelse([
      +Local Variables:
      +eval: (add-hook 'after-save-hook '(lambda () (run-command nil "make")) nil 'local)
      +end:
      +])dnl
      
      From 2cb55e23f89d5ddb044314ef0f4a0228dbb416e1 Mon Sep 17 00:00:00 2001
      From: Suzanne Millstein 
      Date: Fri, 14 Nov 2025 09:06:18 -0800
      Subject: [PATCH 68/82] Split daikon test (#236)
      
      ---
       .azure/azure-pipelines.yml | 36 +++++++++++++++++++++++++++++++++---
       1 file changed, 33 insertions(+), 3 deletions(-)
      
      diff --git a/.azure/azure-pipelines.yml b/.azure/azure-pipelines.yml
      index fee7502c895..8deef72867e 100644
      --- a/.azure/azure-pipelines.yml
      +++ b/.azure/azure-pipelines.yml
      @@ -204,7 +204,7 @@ jobs:
       #     displayName: publish all.tgz
       
       
      -- job: test_daikon
      +- job: test_daikon_part1
         pool:
           vmImage: 'ubuntu-latest'
         container: mdernst/cf-ubuntu-jdk17:latest
      @@ -216,8 +216,38 @@ jobs:
           displayName: clone git-scripts
         - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
           displayName: clone checker-framework
      -  - bash: (cd ../checker-framework && checker/bin-devel/test-daikon.sh)
      -    displayName: test-daikon.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-daikon-part1.sh)
      +    displayName: test-daikon-part1.sh
      +
      +- job: test_daikon_part2
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk17:latest
      +  timeoutInMinutes: 70
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-daikon-part2.sh)
      +    displayName: test-daikon-part2.sh
      +
      +- job: test_daikon_part3
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk17:latest
      +  timeoutInMinutes: 70
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-daikon-part3.sh)
      +    displayName: test-daikon-part3.sh
       
       - job: test_plume_lib
         pool:
      
      From c25d8014c8d6aebe0844eab844f23cbc0d880a37 Mon Sep 17 00:00:00 2001
      From: Suzanne Millstein 
      Date: Fri, 14 Nov 2025 09:46:38 -0800
      Subject: [PATCH 69/82] Improve documentation of jdk17u repository
      
      ---
       README.md | 1 +
       1 file changed, 1 insertion(+)
      
      diff --git a/README.md b/README.md
      index 4b960ad8ddd..589cb9ac79e 100644
      --- a/README.md
      +++ b/README.md
      @@ -150,6 +150,7 @@ Make changes in the `typetools/jdk` repository.
       (Note that this README file appears in both the `typetools/jdk` and `typetools/jdk17u` repositories!)
       
       To update jdk17u from its upstreams:
      +(These are the only edits to jdk17u allowed, plus changes needed to resolve merge conflicts.)
       ```
       cd jdk17u
       git pull
      
      From 9bf1120c6de1cf5fe5299940a834468c7308bdae Mon Sep 17 00:00:00 2001
      From: Michael Ernst 
      Date: Fri, 14 Nov 2025 13:27:03 -0800
      Subject: [PATCH 70/82] Split cftests_all job
      
      ---
       .azure/azure-pipelines.yml    | 208 +++++++++++++++++++++++++++-------
       .azure/azure-pipelines.yml.m4 |  19 +++-
       .azure/defs.m4                |  30 +----
       3 files changed, 189 insertions(+), 68 deletions(-)
      
      diff --git a/.azure/azure-pipelines.yml b/.azure/azure-pipelines.yml
      index 8deef72867e..f218a2f7c9a 100644
      --- a/.azure/azure-pipelines.yml
      +++ b/.azure/azure-pipelines.yml
      @@ -2,8 +2,6 @@
       
       
       
      -
      -
       variables:
         system.debug: true
       
      @@ -107,7 +105,7 @@ jobs:
         #   timeoutInMinutes: 0
         #   displayName: make run-test
       
      -- job: test_cftests_all_jdk11
      +- job: test_cftests_junit_jdk11
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -119,27 +117,51 @@ jobs:
           displayName: clone git-scripts
         - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
           displayName: clone checker-framework
      -# test-cftests-all.sh sometimes runs out of memory (under JDK 11 and 17), but running its component parts in sequence does not.
      -#   - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh)
      -#     displayName: test-cftests-all.sh
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh)
           displayName: test-cftests-junit.sh
      +- job: test_cftests_nonjunit_jdk11
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk11:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh)
           displayName: test-cftests-nonjunit.sh
      +- job: test_cftests_inference_jdk11
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk11:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh)
           displayName: test-cftests-inference.sh
      +- job: test_cftests_typecheck_jdk11
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk11:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh)
           displayName: test-typecheck.sh
      -## Here is how to create artifacts that can be downloaded.
      -#   - bash: (cd ../checker-framework/checker/build/jtregJdk11/ && tar -czvf all.tgz all)
      -#     condition: succeededOrFailed()
      -#     displayName: tar jtregJdk11/all
      -#   - publish: $(System.DefaultWorkingDirectory)/../checker-framework/checker/build/jtregJdk11/all.tgz
      -#     artifact: all.tgz
      -#     condition: failed()
      -#     displayName: publish all.tgz
      -
      -- job: test_cftests_all_jdk17
      +- job: test_cftests_junit_jdk17
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -151,27 +173,79 @@ jobs:
           displayName: clone git-scripts
         - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
           displayName: clone checker-framework
      -# test-cftests-all.sh sometimes runs out of memory (under JDK 11 and 17), but running its component parts in sequence does not.
      -#   - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh)
      -#     displayName: test-cftests-all.sh
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh)
           displayName: test-cftests-junit.sh
      +- job: test_cftests_nonjunit_jdk17
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk17:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh)
           displayName: test-cftests-nonjunit.sh
      +- job: test_cftests_inference_jdk17
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk17:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh)
           displayName: test-cftests-inference.sh
      +- job: test_cftests_typecheck_jdk17
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk17:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh)
           displayName: test-typecheck.sh
      -## Here is how to create artifacts that can be downloaded.
      -#   - bash: (cd ../checker-framework/checker/build/jtregJdk17/ && tar -czvf all.tgz all)
      -#     condition: succeededOrFailed()
      -#     displayName: tar jtregJdk17/all
      -#   - publish: $(System.DefaultWorkingDirectory)/../checker-framework/checker/build/jtregJdk17/all.tgz
      -#     artifact: all.tgz
      -#     condition: failed()
      -#     displayName: publish all.tgz
      -
      -- job: test_cftests_all_jdk21
      +- job: test_cftests_junit_jdk21
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk21:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh)
      +    displayName: test-cftests-junit.sh
      +- job: test_cftests_nonjunit_jdk21
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk21:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh)
      +    displayName: test-cftests-nonjunit.sh
      +- job: test_cftests_inference_jdk21
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -183,26 +257,78 @@ jobs:
           displayName: clone git-scripts
         - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
           displayName: clone checker-framework
      -# test-cftests-all.sh sometimes runs out of memory (under JDK 11 and 17), but running its component parts in sequence does not.
      -#   - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh)
      -#     displayName: test-cftests-all.sh
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh)
      +    displayName: test-cftests-inference.sh
      +- job: test_cftests_typecheck_jdk21
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk21:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh)
      +    displayName: test-typecheck.sh
      +- job: test_cftests_junit_jdk25
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk25:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh)
           displayName: test-cftests-junit.sh
      +- job: test_cftests_nonjunit_jdk25
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk25:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh)
           displayName: test-cftests-nonjunit.sh
      +- job: test_cftests_inference_jdk25
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk25:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh)
           displayName: test-cftests-inference.sh
      +- job: test_cftests_typecheck_jdk25
      +  timeoutInMinutes: 120
      +  pool:
      +    vmImage: 'ubuntu-latest'
      +  container: mdernst/cf-ubuntu-jdk25:latest
      +  steps:
      +  - checkout: self
      +    fetchDepth: 25
      +  - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --depth=1 -q https://github.com/plume-lib/git-scripts.git
      +    displayName: clone git-scripts
      +  - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
      +    displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh)
           displayName: test-typecheck.sh
      -## Here is how to create artifacts that can be downloaded.
      -#   - bash: (cd ../checker-framework/checker/build/jtregJdk21/ && tar -czvf all.tgz all)
      -#     condition: succeededOrFailed()
      -#     displayName: tar jtregJdk21/all
      -#   - publish: $(System.DefaultWorkingDirectory)/../checker-framework/checker/build/jtregJdk21/all.tgz
      -#     artifact: all.tgz
      -#     condition: failed()
      -#     displayName: publish all.tgz
      -
       
       - job: test_daikon_part1
         pool:
      diff --git a/.azure/azure-pipelines.yml.m4 b/.azure/azure-pipelines.yml.m4
      index c910f4fd917..a16d6af702f 100644
      --- a/.azure/azure-pipelines.yml.m4
      +++ b/.azure/azure-pipelines.yml.m4
      @@ -106,9 +106,22 @@ jobs:
         #   timeoutInMinutes: 0
         #   displayName: make run-test
       
      -cftests_all_job(11)
      -cftests_all_job(17)
      -cftests_all_job(21)
      +cftests_job(junit, cftests-junit, 11)
      +cftests_job(nonjunit, cftests-nonjunit, 11)
      +cftests_job(inference, cftests-inference, 11)
      +cftests_job(typecheck, typecheck, 11)
      +cftests_job(junit, cftests-junit, 17)
      +cftests_job(nonjunit, cftests-nonjunit, 17)
      +cftests_job(inference, cftests-inference, 17)
      +cftests_job(typecheck, typecheck, 17)
      +cftests_job(junit, cftests-junit, 21)
      +cftests_job(nonjunit, cftests-nonjunit, 21)
      +cftests_job(inference, cftests-inference, 21)
      +cftests_job(typecheck, typecheck, 21)
      +cftests_job(junit, cftests-junit, 25)
      +cftests_job(nonjunit, cftests-nonjunit, 25)
      +cftests_job(inference, cftests-inference, 25)
      +cftests_job(typecheck, typecheck, 25)
       
       daikon_job
       
      diff --git a/.azure/defs.m4 b/.azure/defs.m4
      index 28743248917..ccc967bed9f 100644
      --- a/.azure/defs.m4
      +++ b/.azure/defs.m4
      @@ -11,12 +11,12 @@ define([docker_testing], [])dnl
       ifelse([uncomment the next line to use the "testing" Docker images])dnl
       ifelse([define([docker_testing], [-testing])])dnl
       dnl
      -define([cftests_all_job], [dnl
      -- job: test_cftests_all_jdk$1
      +define([cftests_job], [dnl
      +- job: test_cftests_$1_jdk$3
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      -  container: mdernst/cf-ubuntu-jdk$1:latest
      +  container: mdernst/cf-ubuntu-jdk$3:latest
         steps:
         - checkout: self
           fetchDepth: 25
      @@ -24,27 +24,9 @@ define([cftests_all_job], [dnl
           displayName: clone git-scripts
         - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
           displayName: clone checker-framework
      -# test-cftests-all.sh sometimes runs out of memory (under JDK 11 and 17), but running its component parts in sequence does not.
      -#   - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh)
      -#     displayName: test-cftests-all.sh
      -  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh)
      -    displayName: test-cftests-junit.sh
      -  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh)
      -    displayName: test-cftests-nonjunit.sh
      -  - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh)
      -    displayName: test-cftests-inference.sh
      -  - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh)
      -    displayName: test-typecheck.sh
      -## Here is how to create artifacts that can be downloaded.
      -#   - bash: (cd ../checker-framework/checker/build/jtregJdk$1/ && tar -czvf all.tgz all)
      -#     condition: succeededOrFailed()
      -#     displayName: tar jtregJdk$1/all
      -#   - publish: $(System.DefaultWorkingDirectory)/../checker-framework/checker/build/jtregJdk$1/all.tgz
      -#     artifact: all.tgz
      -#     condition: failed()
      -#     displayName: publish all.tgz
      -])
      -
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-$2.sh)
      +    displayName: test-$2.sh])dnl
      +dnl
       define([junit_job], [dnl
         - job: junit_jdk$1
       ifelse($1,canary_version,,[    dependsOn:
      
      From b3c963f85050d48a7ec1b69466e6056a33d4532b Mon Sep 17 00:00:00 2001
      From: Michael Ernst 
      Date: Fri, 14 Nov 2025 15:03:42 -0800
      Subject: [PATCH 71/82] Generate Daikon jobs
      
      ---
       .azure/azure-pipelines.yml    | 2 --
       .azure/azure-pipelines.yml.m4 | 4 +++-
       .azure/defs.m4                | 6 +++---
       3 files changed, 6 insertions(+), 6 deletions(-)
      
      diff --git a/.azure/azure-pipelines.yml b/.azure/azure-pipelines.yml
      index f218a2f7c9a..4f22eb29b78 100644
      --- a/.azure/azure-pipelines.yml
      +++ b/.azure/azure-pipelines.yml
      @@ -344,7 +344,6 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-daikon-part1.sh)
           displayName: test-daikon-part1.sh
      -
       - job: test_daikon_part2
         pool:
           vmImage: 'ubuntu-latest'
      @@ -359,7 +358,6 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-daikon-part2.sh)
           displayName: test-daikon-part2.sh
      -
       - job: test_daikon_part3
         pool:
           vmImage: 'ubuntu-latest'
      diff --git a/.azure/azure-pipelines.yml.m4 b/.azure/azure-pipelines.yml.m4
      index a16d6af702f..231ad5c5cd9 100644
      --- a/.azure/azure-pipelines.yml.m4
      +++ b/.azure/azure-pipelines.yml.m4
      @@ -123,7 +123,9 @@ cftests_job(nonjunit, cftests-nonjunit, 25)
       cftests_job(inference, cftests-inference, 25)
       cftests_job(typecheck, typecheck, 25)
       
      -daikon_job
      +daikon_job(1)
      +daikon_job(2)
      +daikon_job(3)
       
       plume_lib_job(canary_version)
       
      diff --git a/.azure/defs.m4 b/.azure/defs.m4
      index ccc967bed9f..090da411788 100644
      --- a/.azure/defs.m4
      +++ b/.azure/defs.m4
      @@ -150,7 +150,7 @@ ifelse($1,canary_version,[dnl
               displayName: test-typecheck.sh])])dnl
       dnl
       define([daikon_job], [dnl
      -- job: test_daikon
      +- job: test_daikon_part$1
         pool:
           vmImage: 'ubuntu-latest'
         container: mdernst/cf-ubuntu-jdk17:latest
      @@ -162,8 +162,8 @@ define([daikon_job], [dnl
           displayName: clone git-scripts
         - bash: /tmp/$USER/git-scripts/git-clone-related typetools checker-framework
           displayName: clone checker-framework
      -  - bash: (cd ../checker-framework && checker/bin-devel/test-daikon.sh)
      -    displayName: test-daikon.sh])dnl
      +  - bash: (cd ../checker-framework && checker/bin-devel/test-daikon-part$1.sh)
      +    displayName: test-daikon-part$1.sh])dnl
       dnl
       define([plume_lib_job], [dnl
       - job: test_plume_lib
      
      From 48075acbca0d500e5d84d27b7a2b66826bc698fb Mon Sep 17 00:00:00 2001
      From: Michael Ernst 
      Date: Sat, 15 Nov 2025 20:50:20 -0800
      Subject: [PATCH 72/82] Shorten job names
      
      ---
       .azure/azure-pipelines.yml | 32 ++++++++++++++++----------------
       .azure/defs.m4             |  2 +-
       2 files changed, 17 insertions(+), 17 deletions(-)
      
      diff --git a/.azure/azure-pipelines.yml b/.azure/azure-pipelines.yml
      index 4f22eb29b78..518cb7f3bbd 100644
      --- a/.azure/azure-pipelines.yml
      +++ b/.azure/azure-pipelines.yml
      @@ -105,7 +105,7 @@ jobs:
         #   timeoutInMinutes: 0
         #   displayName: make run-test
       
      -- job: test_cftests_junit_jdk11
      +- job: cftests_junit_jdk11
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -119,7 +119,7 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh)
           displayName: test-cftests-junit.sh
      -- job: test_cftests_nonjunit_jdk11
      +- job: cftests_nonjunit_jdk11
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -133,7 +133,7 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh)
           displayName: test-cftests-nonjunit.sh
      -- job: test_cftests_inference_jdk11
      +- job: cftests_inference_jdk11
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -147,7 +147,7 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh)
           displayName: test-cftests-inference.sh
      -- job: test_cftests_typecheck_jdk11
      +- job: cftests_typecheck_jdk11
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -161,7 +161,7 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh)
           displayName: test-typecheck.sh
      -- job: test_cftests_junit_jdk17
      +- job: cftests_junit_jdk17
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -175,7 +175,7 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh)
           displayName: test-cftests-junit.sh
      -- job: test_cftests_nonjunit_jdk17
      +- job: cftests_nonjunit_jdk17
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -189,7 +189,7 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh)
           displayName: test-cftests-nonjunit.sh
      -- job: test_cftests_inference_jdk17
      +- job: cftests_inference_jdk17
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -203,7 +203,7 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh)
           displayName: test-cftests-inference.sh
      -- job: test_cftests_typecheck_jdk17
      +- job: cftests_typecheck_jdk17
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -217,7 +217,7 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh)
           displayName: test-typecheck.sh
      -- job: test_cftests_junit_jdk21
      +- job: cftests_junit_jdk21
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -231,7 +231,7 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh)
           displayName: test-cftests-junit.sh
      -- job: test_cftests_nonjunit_jdk21
      +- job: cftests_nonjunit_jdk21
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -245,7 +245,7 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh)
           displayName: test-cftests-nonjunit.sh
      -- job: test_cftests_inference_jdk21
      +- job: cftests_inference_jdk21
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -259,7 +259,7 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh)
           displayName: test-cftests-inference.sh
      -- job: test_cftests_typecheck_jdk21
      +- job: cftests_typecheck_jdk21
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -273,7 +273,7 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-typecheck.sh)
           displayName: test-typecheck.sh
      -- job: test_cftests_junit_jdk25
      +- job: cftests_junit_jdk25
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -287,7 +287,7 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-junit.sh)
           displayName: test-cftests-junit.sh
      -- job: test_cftests_nonjunit_jdk25
      +- job: cftests_nonjunit_jdk25
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -301,7 +301,7 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-nonjunit.sh)
           displayName: test-cftests-nonjunit.sh
      -- job: test_cftests_inference_jdk25
      +- job: cftests_inference_jdk25
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      @@ -315,7 +315,7 @@ jobs:
           displayName: clone checker-framework
         - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-inference.sh)
           displayName: test-cftests-inference.sh
      -- job: test_cftests_typecheck_jdk25
      +- job: cftests_typecheck_jdk25
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      diff --git a/.azure/defs.m4 b/.azure/defs.m4
      index 090da411788..1d651873c28 100644
      --- a/.azure/defs.m4
      +++ b/.azure/defs.m4
      @@ -12,7 +12,7 @@ ifelse([uncomment the next line to use the "testing" Docker images])dnl
       ifelse([define([docker_testing], [-testing])])dnl
       dnl
       define([cftests_job], [dnl
      -- job: test_cftests_$1_jdk$3
      +- job: cftests_$1_jdk$3
         timeoutInMinutes: 120
         pool:
           vmImage: 'ubuntu-latest'
      
      From 3ebc5f014cb6c76d7f0e5b00193597de7b77681f Mon Sep 17 00:00:00 2001
      From: Suzanne Millstein 
      Date: Wed, 19 Nov 2025 10:38:57 -0800
      Subject: [PATCH 73/82] Annotated io/nio/concurrent exceptions (#244)
      
      Co-authored-by: Davy Landman 
      ---
       src/java.base/share/classes/java/io/EOFException.java  |  6 +++++-
       .../share/classes/java/io/FileNotFoundException.java   |  7 +++++--
       .../share/classes/java/io/NotActiveException.java      |  6 +++++-
       .../classes/java/io/NotSerializableException.java      |  6 +++++-
       .../share/classes/java/io/OptionalDataException.java   |  3 +++
       .../classes/java/io/StreamCorruptedException.java      |  5 ++++-
       .../share/classes/java/io/SyncFailedException.java     |  6 +++++-
       .../share/classes/java/io/UTFDataFormatException.java  |  6 +++++-
       .../classes/java/io/UnsupportedEncodingException.java  |  6 +++++-
       .../share/classes/java/io/WriteAbortedException.java   |  6 ++++--
       .../classes/java/nio/file/AccessDeniedException.java   |  9 ++++++---
       .../java/nio/file/AtomicMoveNotSupportedException.java | 10 +++++++---
       .../java/nio/file/DirectoryIteratorException.java      |  4 ++++
       .../java/nio/file/DirectoryNotEmptyException.java      |  5 ++++-
       .../java/nio/file/FileAlreadyExistsException.java      |  8 ++++++--
       .../nio/file/FileSystemAlreadyExistsException.java     |  6 +++++-
       .../classes/java/nio/file/FileSystemLoopException.java |  6 +++++-
       .../java/nio/file/FileSystemNotFoundException.java     |  6 +++++-
       .../classes/java/nio/file/InvalidPathException.java    |  3 +++
       .../classes/java/nio/file/NoSuchFileException.java     |  8 ++++++--
       .../classes/java/nio/file/NotDirectoryException.java   |  6 +++++-
       .../share/classes/java/nio/file/NotLinkException.java  |  8 ++++++--
       .../java/nio/file/ProviderMismatchException.java       |  6 +++++-
       .../java/nio/file/ProviderNotFoundException.java       |  6 +++++-
       .../java/nio/file/ReadOnlyFileSystemException.java     |  3 +++
       .../java/util/concurrent/BrokenBarrierException.java   |  6 +++++-
       26 files changed, 126 insertions(+), 31 deletions(-)
      
      diff --git a/src/java.base/share/classes/java/io/EOFException.java b/src/java.base/share/classes/java/io/EOFException.java
      index dcc1315e762..ab2b9a86ba1 100644
      --- a/src/java.base/share/classes/java/io/EOFException.java
      +++ b/src/java.base/share/classes/java/io/EOFException.java
      @@ -25,6 +25,9 @@
       
       package java.io;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Signals that an end of file or end of stream has been reached
        * unexpectedly during input.
      @@ -38,6 +41,7 @@
        * @see     java.io.IOException
        * @since   1.0
        */
      +@AnnotatedFor({"nullness"})
       public class EOFException extends IOException {
           @java.io.Serial
           private static final long serialVersionUID = 6433858223774886977L;
      @@ -58,7 +62,7 @@ public EOFException() {
            *
            * @param   s   the detail message.
            */
      -    public EOFException(String s) {
      +    public EOFException(@Nullable String s) {
               super(s);
           }
       }
      diff --git a/src/java.base/share/classes/java/io/FileNotFoundException.java b/src/java.base/share/classes/java/io/FileNotFoundException.java
      index 8d13aa3fdb9..331447c4d7b 100644
      --- a/src/java.base/share/classes/java/io/FileNotFoundException.java
      +++ b/src/java.base/share/classes/java/io/FileNotFoundException.java
      @@ -25,6 +25,8 @@
       
       package java.io;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
       
       /**
        * Signals that an attempt to open the file denoted by a specified pathname
      @@ -39,6 +41,7 @@
        * @since   1.0
        */
       
      +@AnnotatedFor({"nullness"})
       public class FileNotFoundException extends IOException {
           @java.io.Serial
           private static final long serialVersionUID = -897856973823710492L;
      @@ -60,7 +63,7 @@ public FileNotFoundException() {
            *
            * @param   s   the detail message.
            */
      -    public FileNotFoundException(String s) {
      +    public FileNotFoundException(@Nullable String s) {
               super(s);
           }
       
      @@ -73,7 +76,7 @@ public FileNotFoundException(String s) {
            *
            * @since 1.2
            */
      -    private FileNotFoundException(String path, String reason) {
      +    private FileNotFoundException(String path, @Nullable String reason) {
               super(path + ((reason == null)
                             ? ""
                             : " (" + reason + ")"));
      diff --git a/src/java.base/share/classes/java/io/NotActiveException.java b/src/java.base/share/classes/java/io/NotActiveException.java
      index 3b8b281cbf4..7835518fdd0 100644
      --- a/src/java.base/share/classes/java/io/NotActiveException.java
      +++ b/src/java.base/share/classes/java/io/NotActiveException.java
      @@ -25,11 +25,15 @@
       
       package java.io;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Thrown when serialization or deserialization is not active.
        *
        * @since   1.1
        */
      +@AnnotatedFor({"nullness"})
       public class NotActiveException extends ObjectStreamException {
       
           @java.io.Serial
      @@ -40,7 +44,7 @@ public class NotActiveException extends ObjectStreamException {
            *
            * @param reason  a String describing the reason for the exception.
            */
      -    public NotActiveException(String reason) {
      +    public NotActiveException(@Nullable String reason) {
               super(reason);
           }
       
      diff --git a/src/java.base/share/classes/java/io/NotSerializableException.java b/src/java.base/share/classes/java/io/NotSerializableException.java
      index d1010188272..a660b09e233 100644
      --- a/src/java.base/share/classes/java/io/NotSerializableException.java
      +++ b/src/java.base/share/classes/java/io/NotSerializableException.java
      @@ -25,6 +25,9 @@
       
       package java.io;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Thrown when an instance is required to have a Serializable interface.
        * The serialization runtime or the class of the instance can throw
      @@ -32,6 +35,7 @@
        *
        * @since   1.1
        */
      +@AnnotatedFor({"nullness"})
       public class NotSerializableException extends ObjectStreamException {
       
           @java.io.Serial
      @@ -42,7 +46,7 @@ public class NotSerializableException extends ObjectStreamException {
            *
            * @param classname Class of the instance being serialized/deserialized.
            */
      -    public NotSerializableException(String classname) {
      +    public NotSerializableException(@Nullable String classname) {
               super(classname);
           }
       
      diff --git a/src/java.base/share/classes/java/io/OptionalDataException.java b/src/java.base/share/classes/java/io/OptionalDataException.java
      index f98bf079e8e..e62169b36fd 100644
      --- a/src/java.base/share/classes/java/io/OptionalDataException.java
      +++ b/src/java.base/share/classes/java/io/OptionalDataException.java
      @@ -24,6 +24,8 @@
        */
       package java.io;
       
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Exception indicating the failure of an object read operation due to
        * unread primitive data, or the end of data belonging to a serialized
      @@ -44,6 +46,7 @@
        *
        * @since   1.1
        */
      +@AnnotatedFor({"nullness"})
       public class OptionalDataException extends ObjectStreamException {
       
           @java.io.Serial
      diff --git a/src/java.base/share/classes/java/io/StreamCorruptedException.java b/src/java.base/share/classes/java/io/StreamCorruptedException.java
      index 5124c5ce657..408443f8a5b 100644
      --- a/src/java.base/share/classes/java/io/StreamCorruptedException.java
      +++ b/src/java.base/share/classes/java/io/StreamCorruptedException.java
      @@ -25,12 +25,15 @@
       
       package java.io;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
       /**
        * Thrown when control information that was read from an object stream
        * violates internal consistency checks.
        *
        * @since   1.1
        */
      +@AnnotatedFor({"nullness"})
       public class StreamCorruptedException extends ObjectStreamException {
       
           @java.io.Serial
      @@ -41,7 +44,7 @@ public class StreamCorruptedException extends ObjectStreamException {
            *
            * @param reason  String describing the reason for the exception.
            */
      -    public StreamCorruptedException(String reason) {
      +    public StreamCorruptedException(@Nullable String reason) {
               super(reason);
           }
       
      diff --git a/src/java.base/share/classes/java/io/SyncFailedException.java b/src/java.base/share/classes/java/io/SyncFailedException.java
      index e940b5a7e56..aedabf3add3 100644
      --- a/src/java.base/share/classes/java/io/SyncFailedException.java
      +++ b/src/java.base/share/classes/java/io/SyncFailedException.java
      @@ -25,6 +25,9 @@
       
       package java.io;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Signals that a sync operation has failed.
        *
      @@ -33,6 +36,7 @@
        * @see     java.io.IOException
        * @since   1.1
        */
      +@AnnotatedFor({"nullness"})
       public class SyncFailedException extends IOException {
           @java.io.Serial
           private static final long serialVersionUID = -2353342684412443330L;
      @@ -43,7 +47,7 @@ public class SyncFailedException extends IOException {
            *
            * @param desc  a String describing the exception.
            */
      -    public SyncFailedException(String desc) {
      +    public SyncFailedException(@Nullable String desc) {
               super(desc);
           }
       }
      diff --git a/src/java.base/share/classes/java/io/UTFDataFormatException.java b/src/java.base/share/classes/java/io/UTFDataFormatException.java
      index bb8eb3b7d81..cc45ea2d3d3 100644
      --- a/src/java.base/share/classes/java/io/UTFDataFormatException.java
      +++ b/src/java.base/share/classes/java/io/UTFDataFormatException.java
      @@ -25,6 +25,9 @@
       
       package java.io;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Signals that a malformed string in
        * modified UTF-8
      @@ -42,6 +45,7 @@
        * @see     java.io.IOException
        * @since   1.0
        */
      +@AnnotatedFor({"nullness"})
       public class UTFDataFormatException extends IOException {
           @java.io.Serial
           private static final long serialVersionUID = 420743449228280612L;
      @@ -63,7 +67,7 @@ public UTFDataFormatException() {
            *
            * @param   s   the detail message.
            */
      -    public UTFDataFormatException(String s) {
      +    public UTFDataFormatException(@Nullable String s) {
               super(s);
           }
       }
      diff --git a/src/java.base/share/classes/java/io/UnsupportedEncodingException.java b/src/java.base/share/classes/java/io/UnsupportedEncodingException.java
      index b80f453f5c6..48440f8ae19 100644
      --- a/src/java.base/share/classes/java/io/UnsupportedEncodingException.java
      +++ b/src/java.base/share/classes/java/io/UnsupportedEncodingException.java
      @@ -24,12 +24,16 @@
        */
       package java.io;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * The Character Encoding is not supported.
        *
        * @author  Asmus Freytag
        * @since   1.1
        */
      +@AnnotatedFor({"nullness"})
       public class UnsupportedEncodingException
           extends IOException
       {
      @@ -47,7 +51,7 @@ public UnsupportedEncodingException() {
            * Constructs an UnsupportedEncodingException with a detail message.
            * @param s Describes the reason for the exception.
            */
      -    public UnsupportedEncodingException(String s) {
      +    public UnsupportedEncodingException(@Nullable String s) {
               super(s);
           }
       }
      diff --git a/src/java.base/share/classes/java/io/WriteAbortedException.java b/src/java.base/share/classes/java/io/WriteAbortedException.java
      index a179d2d669c..c4f3ed55d31 100644
      --- a/src/java.base/share/classes/java/io/WriteAbortedException.java
      +++ b/src/java.base/share/classes/java/io/WriteAbortedException.java
      @@ -26,6 +26,7 @@
       package java.io;
       
       import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
       
       /**
        * Signals that one of the ObjectStreamExceptions was thrown during a
      @@ -37,6 +38,7 @@
        *
        * @since   1.1
        */
      +@AnnotatedFor({"nullness"})
       public class WriteAbortedException extends ObjectStreamException {
           @java.io.Serial
           private static final long serialVersionUID = -3326426625597282442L;
      @@ -51,7 +53,7 @@ public class WriteAbortedException extends ObjectStreamException {
            * @serial
            */
           @Deprecated(since="17")
      -    public Exception detail;
      +    public @Nullable Exception detail;
       
           /**
            * Constructs a WriteAbortedException with a string describing
      @@ -59,7 +61,7 @@ public class WriteAbortedException extends ObjectStreamException {
            * @param s   String describing the exception.
            * @param ex  Exception causing the abort.
            */
      -    public WriteAbortedException(String s, Exception ex) {
      +    public WriteAbortedException(@Nullable String s, @Nullable Exception ex) {
               super(s);
               initCause(null);  // Disallow subsequent initCause
               detail = ex;
      diff --git a/src/java.base/share/classes/java/nio/file/AccessDeniedException.java b/src/java.base/share/classes/java/nio/file/AccessDeniedException.java
      index 10f0fda3955..d45fca83c0b 100644
      --- a/src/java.base/share/classes/java/nio/file/AccessDeniedException.java
      +++ b/src/java.base/share/classes/java/nio/file/AccessDeniedException.java
      @@ -25,6 +25,9 @@
       
       package java.nio.file;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Checked exception thrown when a file system operation is denied, typically
        * due to a file permission or other access check.
      @@ -36,7 +39,7 @@
        *
        * @since 1.7
        */
      -
      +@AnnotatedFor({"nullness"})
       public class AccessDeniedException
           extends FileSystemException
       {
      @@ -49,7 +52,7 @@ public class AccessDeniedException
            * @param   file
            *          a string identifying the file or {@code null} if not known
            */
      -    public AccessDeniedException(String file) {
      +    public AccessDeniedException(@Nullable String file) {
               super(file);
           }
       
      @@ -63,7 +66,7 @@ public AccessDeniedException(String file) {
            * @param   reason
            *          a reason message with additional information or {@code null}
            */
      -    public AccessDeniedException(String file, String other, String reason) {
      +    public AccessDeniedException(@Nullable String file, @Nullable String other, @Nullable String reason) {
               super(file, other, reason);
           }
       }
      diff --git a/src/java.base/share/classes/java/nio/file/AtomicMoveNotSupportedException.java b/src/java.base/share/classes/java/nio/file/AtomicMoveNotSupportedException.java
      index e08ba0a343c..59a60350485 100644
      --- a/src/java.base/share/classes/java/nio/file/AtomicMoveNotSupportedException.java
      +++ b/src/java.base/share/classes/java/nio/file/AtomicMoveNotSupportedException.java
      @@ -25,6 +25,9 @@
       
       package java.nio.file;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Checked exception thrown when a file cannot be moved as an atomic file system
        * operation.
      @@ -32,6 +35,7 @@
        * @since 1.7
        */
       
      +@AnnotatedFor({"nullness"})
       public class AtomicMoveNotSupportedException
           extends FileSystemException
       {
      @@ -48,9 +52,9 @@ public class AtomicMoveNotSupportedException
            * @param   reason
            *          a reason message with additional information or {@code null}
            */
      -    public AtomicMoveNotSupportedException(String source,
      -                                           String target,
      -                                           String reason)
      +    public AtomicMoveNotSupportedException(@Nullable String source,
      +                                           @Nullable String target,
      +                                           @Nullable String reason)
           {
               super(source, target, reason);
           }
      diff --git a/src/java.base/share/classes/java/nio/file/DirectoryIteratorException.java b/src/java.base/share/classes/java/nio/file/DirectoryIteratorException.java
      index 51fb08759e0..5944e3d4a4a 100644
      --- a/src/java.base/share/classes/java/nio/file/DirectoryIteratorException.java
      +++ b/src/java.base/share/classes/java/nio/file/DirectoryIteratorException.java
      @@ -31,6 +31,9 @@
       import java.io.ObjectInputStream;
       import java.io.InvalidObjectException;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Runtime exception thrown if an I/O error is encountered when iterating over
        * the entries in a directory. The I/O error is retrieved as an {@link
      @@ -40,6 +43,7 @@
        * @see DirectoryStream
        */
       
      +@AnnotatedFor({"nullness"})
       public final class DirectoryIteratorException
           extends ConcurrentModificationException
       {
      diff --git a/src/java.base/share/classes/java/nio/file/DirectoryNotEmptyException.java b/src/java.base/share/classes/java/nio/file/DirectoryNotEmptyException.java
      index 563e0830f06..1dc2c7543ba 100644
      --- a/src/java.base/share/classes/java/nio/file/DirectoryNotEmptyException.java
      +++ b/src/java.base/share/classes/java/nio/file/DirectoryNotEmptyException.java
      @@ -25,6 +25,8 @@
       
       package java.nio.file;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
       /**
        * Checked exception thrown when a file system operation fails because a
        * directory is not empty.
      @@ -32,6 +34,7 @@
        * @since 1.7
        */
       
      +@AnnotatedFor({"nullness"})
       public class DirectoryNotEmptyException
           extends FileSystemException
       {
      @@ -44,7 +47,7 @@ public class DirectoryNotEmptyException
            * @param   dir
            *          a string identifying the directory or {@code null} if not known
            */
      -    public DirectoryNotEmptyException(String dir) {
      +    public DirectoryNotEmptyException(@Nullable String dir) {
               super(dir);
           }
       }
      diff --git a/src/java.base/share/classes/java/nio/file/FileAlreadyExistsException.java b/src/java.base/share/classes/java/nio/file/FileAlreadyExistsException.java
      index 90fcbba25be..0586d5e28f4 100644
      --- a/src/java.base/share/classes/java/nio/file/FileAlreadyExistsException.java
      +++ b/src/java.base/share/classes/java/nio/file/FileAlreadyExistsException.java
      @@ -25,6 +25,9 @@
       
       package java.nio.file;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Checked exception thrown when an attempt is made to create a file or
        * directory and a file of that name already exists.
      @@ -32,6 +35,7 @@
        * @since 1.7
        */
       
      +@AnnotatedFor({"nullness"})
       public class FileAlreadyExistsException
           extends FileSystemException
       {
      @@ -44,7 +48,7 @@ public class FileAlreadyExistsException
            * @param   file
            *          a string identifying the file or {@code null} if not known
            */
      -    public FileAlreadyExistsException(String file) {
      +    public FileAlreadyExistsException(@Nullable String file) {
               super(file);
           }
       
      @@ -58,7 +62,7 @@ public FileAlreadyExistsException(String file) {
            * @param   reason
            *          a reason message with additional information or {@code null}
            */
      -    public FileAlreadyExistsException(String file, String other, String reason) {
      +    public FileAlreadyExistsException(@Nullable String file, @Nullable String other, @Nullable String reason) {
               super(file, other, reason);
           }
       }
      diff --git a/src/java.base/share/classes/java/nio/file/FileSystemAlreadyExistsException.java b/src/java.base/share/classes/java/nio/file/FileSystemAlreadyExistsException.java
      index 0f4be9f393a..afa5750db97 100644
      --- a/src/java.base/share/classes/java/nio/file/FileSystemAlreadyExistsException.java
      +++ b/src/java.base/share/classes/java/nio/file/FileSystemAlreadyExistsException.java
      @@ -25,6 +25,9 @@
       
       package java.nio.file;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Runtime exception thrown when an attempt is made to create a file system that
        * already exists.
      @@ -32,6 +35,7 @@
        * @since 1.7
        */
       
      +@AnnotatedFor({"nullness"})
       public class FileSystemAlreadyExistsException
           extends RuntimeException
       {
      @@ -50,7 +54,7 @@ public FileSystemAlreadyExistsException() {
            * @param   msg
            *          the detail message
            */
      -    public FileSystemAlreadyExistsException(String msg) {
      +    public FileSystemAlreadyExistsException(@Nullable String msg) {
               super(msg);
           }
       }
      diff --git a/src/java.base/share/classes/java/nio/file/FileSystemLoopException.java b/src/java.base/share/classes/java/nio/file/FileSystemLoopException.java
      index 0cea2e94abf..b0e0df2dd36 100644
      --- a/src/java.base/share/classes/java/nio/file/FileSystemLoopException.java
      +++ b/src/java.base/share/classes/java/nio/file/FileSystemLoopException.java
      @@ -25,6 +25,9 @@
       
       package java.nio.file;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Checked exception thrown when a file system loop, or cycle, is encountered.
        *
      @@ -32,6 +35,7 @@
        * @see Files#walkFileTree
        */
       
      +@AnnotatedFor({"nullness"})
       public class FileSystemLoopException
           extends FileSystemException
       {
      @@ -45,7 +49,7 @@ public class FileSystemLoopException
            *          a string identifying the file causing the cycle or {@code null} if
            *          not known
            */
      -    public FileSystemLoopException(String file) {
      +    public FileSystemLoopException(@Nullable String file) {
               super(file);
           }
       }
      diff --git a/src/java.base/share/classes/java/nio/file/FileSystemNotFoundException.java b/src/java.base/share/classes/java/nio/file/FileSystemNotFoundException.java
      index 0b170fba9a7..c26f478007e 100644
      --- a/src/java.base/share/classes/java/nio/file/FileSystemNotFoundException.java
      +++ b/src/java.base/share/classes/java/nio/file/FileSystemNotFoundException.java
      @@ -25,12 +25,16 @@
       
       package java.nio.file;
       
      +
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
       /**
        * Runtime exception thrown when a file system cannot be found.
        *
        * @since 1.7
        */
       
      +@AnnotatedFor({"nullness"})
       public class FileSystemNotFoundException
           extends RuntimeException
       {
      @@ -49,7 +53,7 @@ public FileSystemNotFoundException() {
            * @param   msg
            *          the detail message
            */
      -    public FileSystemNotFoundException(String msg) {
      +    public FileSystemNotFoundException(@Nullable String msg) {
               super(msg);
           }
       }
      diff --git a/src/java.base/share/classes/java/nio/file/InvalidPathException.java b/src/java.base/share/classes/java/nio/file/InvalidPathException.java
      index bb28b61b83b..83f77419327 100644
      --- a/src/java.base/share/classes/java/nio/file/InvalidPathException.java
      +++ b/src/java.base/share/classes/java/nio/file/InvalidPathException.java
      @@ -25,6 +25,8 @@
       
       package java.nio.file;
       
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Unchecked exception thrown when path string cannot be converted into a
        * {@link Path} because the path string contains invalid characters, or
      @@ -33,6 +35,7 @@
        * @since 1.7
        */
       
      +@AnnotatedFor({"nullness"})
       public class InvalidPathException
           extends IllegalArgumentException
       {
      diff --git a/src/java.base/share/classes/java/nio/file/NoSuchFileException.java b/src/java.base/share/classes/java/nio/file/NoSuchFileException.java
      index 73c37e60d57..56858158e39 100644
      --- a/src/java.base/share/classes/java/nio/file/NoSuchFileException.java
      +++ b/src/java.base/share/classes/java/nio/file/NoSuchFileException.java
      @@ -25,6 +25,9 @@
       
       package java.nio.file;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Checked exception thrown when an attempt is made to access a file that does
        * not exist.
      @@ -32,6 +35,7 @@
        * @since 1.7
        */
       
      +@AnnotatedFor({"nullness"})
       public class NoSuchFileException
           extends FileSystemException
       {
      @@ -44,7 +48,7 @@ public class NoSuchFileException
            * @param   file
            *          a string identifying the file or {@code null} if not known.
            */
      -    public NoSuchFileException(String file) {
      +    public NoSuchFileException(@Nullable String file) {
               super(file);
           }
       
      @@ -58,7 +62,7 @@ public NoSuchFileException(String file) {
            * @param   reason
            *          a reason message with additional information or {@code null}
            */
      -    public NoSuchFileException(String file, String other, String reason) {
      +    public NoSuchFileException(@Nullable String file, @Nullable String other, @Nullable String reason) {
               super(file, other, reason);
           }
       }
      diff --git a/src/java.base/share/classes/java/nio/file/NotDirectoryException.java b/src/java.base/share/classes/java/nio/file/NotDirectoryException.java
      index 225bd2494ff..bad62317c77 100644
      --- a/src/java.base/share/classes/java/nio/file/NotDirectoryException.java
      +++ b/src/java.base/share/classes/java/nio/file/NotDirectoryException.java
      @@ -25,6 +25,9 @@
       
       package java.nio.file;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Checked exception thrown when a file system operation, intended for a
        * directory, fails because the file is not a directory.
      @@ -32,6 +35,7 @@
        * @since 1.7
        */
       
      +@AnnotatedFor({"nullness"})
       public class NotDirectoryException
           extends FileSystemException
       {
      @@ -44,7 +48,7 @@ public class NotDirectoryException
            * @param   file
            *          a string identifying the file or {@code null} if not known
            */
      -    public NotDirectoryException(String file) {
      +    public NotDirectoryException(@Nullable String file) {
               super(file);
           }
       }
      diff --git a/src/java.base/share/classes/java/nio/file/NotLinkException.java b/src/java.base/share/classes/java/nio/file/NotLinkException.java
      index 02563d35a11..cc8eb09aa1d 100644
      --- a/src/java.base/share/classes/java/nio/file/NotLinkException.java
      +++ b/src/java.base/share/classes/java/nio/file/NotLinkException.java
      @@ -25,6 +25,9 @@
       
       package java.nio.file;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Checked exception thrown when a file system operation fails because a file
        * is not a symbolic link.
      @@ -32,6 +35,7 @@
        * @since 1.7
        */
       
      +@AnnotatedFor({"nullness"})
       public class NotLinkException
           extends FileSystemException
       {
      @@ -44,7 +48,7 @@ public class NotLinkException
            * @param   file
            *          a string identifying the file or {@code null} if not known
            */
      -    public NotLinkException(String file) {
      +    public NotLinkException(@Nullable String file) {
               super(file);
           }
       
      @@ -58,7 +62,7 @@ public NotLinkException(String file) {
            * @param   reason
            *          a reason message with additional information or {@code null}
            */
      -    public NotLinkException(String file, String other, String reason) {
      +    public NotLinkException(@Nullable String file, @Nullable String other, @Nullable String reason) {
               super(file, other, reason);
           }
       }
      diff --git a/src/java.base/share/classes/java/nio/file/ProviderMismatchException.java b/src/java.base/share/classes/java/nio/file/ProviderMismatchException.java
      index 70c1fad64ab..78d9d0cb40b 100644
      --- a/src/java.base/share/classes/java/nio/file/ProviderMismatchException.java
      +++ b/src/java.base/share/classes/java/nio/file/ProviderMismatchException.java
      @@ -25,6 +25,9 @@
       
       package java.nio.file;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Unchecked exception thrown when an attempt is made to invoke a method on an
        * object created by one file system provider with a parameter created by a
      @@ -32,6 +35,7 @@
        *
        * @since 1.7
        */
      +@AnnotatedFor({"nullness"})
       public class ProviderMismatchException
           extends java.lang.IllegalArgumentException
       {
      @@ -50,7 +54,7 @@ public ProviderMismatchException() {
            * @param   msg
            *          the detail message
            */
      -    public ProviderMismatchException(String msg) {
      +    public ProviderMismatchException(@Nullable String msg) {
               super(msg);
           }
       }
      diff --git a/src/java.base/share/classes/java/nio/file/ProviderNotFoundException.java b/src/java.base/share/classes/java/nio/file/ProviderNotFoundException.java
      index 804f4996de2..192eae1f802 100644
      --- a/src/java.base/share/classes/java/nio/file/ProviderNotFoundException.java
      +++ b/src/java.base/share/classes/java/nio/file/ProviderNotFoundException.java
      @@ -25,12 +25,16 @@
       
       package java.nio.file;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Runtime exception thrown when a provider of the required type cannot be found.
        *
        * @since 1.7
        */
       
      +@AnnotatedFor({"nullness"})
       public class ProviderNotFoundException
           extends RuntimeException
       {
      @@ -49,7 +53,7 @@ public ProviderNotFoundException() {
            * @param   msg
            *          the detail message
            */
      -    public ProviderNotFoundException(String msg) {
      +    public ProviderNotFoundException(@Nullable String msg) {
               super(msg);
           }
       }
      diff --git a/src/java.base/share/classes/java/nio/file/ReadOnlyFileSystemException.java b/src/java.base/share/classes/java/nio/file/ReadOnlyFileSystemException.java
      index d187ef96b68..4284144164f 100644
      --- a/src/java.base/share/classes/java/nio/file/ReadOnlyFileSystemException.java
      +++ b/src/java.base/share/classes/java/nio/file/ReadOnlyFileSystemException.java
      @@ -25,6 +25,8 @@
       
       package java.nio.file;
       
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Unchecked exception thrown when an attempt is made to update an object
        * associated with a {@link FileSystem#isReadOnly() read-only} {@code FileSystem}.
      @@ -32,6 +34,7 @@
        * @since 1.7
        */
       
      +@AnnotatedFor({"nullness"})
       public class ReadOnlyFileSystemException
           extends UnsupportedOperationException
       {
      diff --git a/src/java.base/share/classes/java/util/concurrent/BrokenBarrierException.java b/src/java.base/share/classes/java/util/concurrent/BrokenBarrierException.java
      index 11f126e015a..fb1e2fa1a97 100644
      --- a/src/java.base/share/classes/java/util/concurrent/BrokenBarrierException.java
      +++ b/src/java.base/share/classes/java/util/concurrent/BrokenBarrierException.java
      @@ -35,6 +35,9 @@
       
       package java.util.concurrent;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * Exception thrown when a thread tries to wait upon a barrier that is
        * in a broken state, or which enters the broken state while the thread
      @@ -45,6 +48,7 @@
        * @since 1.5
        * @author Doug Lea
        */
      +@AnnotatedFor({"nullness"})
       public class BrokenBarrierException extends Exception {
           private static final long serialVersionUID = 7117394618823254244L;
       
      @@ -60,7 +64,7 @@ public BrokenBarrierException() {}
            *
            * @param message the detail message
            */
      -    public BrokenBarrierException(String message) {
      +    public BrokenBarrierException(@Nullable String message) {
               super(message);
           }
       }
      
      From a75a1fec4cff72c277551a0ffe57c3ffd2640954 Mon Sep 17 00:00:00 2001
      From: Suzanne Millstein 
      Date: Fri, 21 Nov 2025 09:07:22 -0800
      Subject: [PATCH 74/82] Added null annotations based on javadoc for the public
       nio classes (#245)
      
      Co-authored-by: Davy Landman 
      Co-authored-by: Davy Landman 
      ---
       src/java.base/share/classes/java/nio/file/FileStore.java | 7 ++++---
       .../share/classes/java/nio/file/FileSystems.java         | 1 +
       .../share/classes/java/nio/file/FileVisitor.java         | 6 +++++-
       .../share/classes/java/nio/file/LinkPermission.java      | 7 ++++++-
       .../classes/java/nio/file/SecureDirectoryStream.java     | 9 +++++++--
       .../share/classes/java/nio/file/SimpleFileVisitor.java   | 5 +++--
       .../share/classes/java/nio/file/WatchEvent.java          | 8 ++++++--
       .../share/classes/java/nio/file/WatchService.java        | 7 ++++---
       .../java/nio/file/attribute/BasicFileAttributeView.java  | 3 +++
       .../java/nio/file/attribute/BasicFileAttributes.java     | 5 +++--
       .../classes/java/nio/file/spi/FileSystemProvider.java    | 7 ++++---
       .../classes/java/nio/file/spi/FileTypeDetector.java      | 5 +++--
       12 files changed, 49 insertions(+), 21 deletions(-)
      
      diff --git a/src/java.base/share/classes/java/nio/file/FileStore.java b/src/java.base/share/classes/java/nio/file/FileStore.java
      index 88c309b4370..18f6aa7982f 100644
      --- a/src/java.base/share/classes/java/nio/file/FileStore.java
      +++ b/src/java.base/share/classes/java/nio/file/FileStore.java
      @@ -27,6 +27,7 @@
       
       import org.checkerframework.checker.interning.qual.UsesObjectEquals;
       import org.checkerframework.framework.qual.AnnotatedFor;
      +import org.checkerframework.checker.nullness.qual.Nullable;
       
       import java.nio.file.attribute.*;
       import java.io.IOException;
      @@ -46,7 +47,7 @@
        * @since 1.7
        */
       
      -@AnnotatedFor({"interning"})
      +@AnnotatedFor({"interning", "nullness"})
       public abstract @UsesObjectEquals class FileStore {
       
           /**
      @@ -215,7 +216,7 @@ public long getBlockSize() throws IOException {
            * @return  a file store attribute view of the specified type or
            *          {@code null} if the attribute view is not available
            */
      -    public abstract  V
      +    public abstract  V
               getFileStoreAttributeView(Class type);
       
           /**
      @@ -251,5 +252,5 @@ public long getBlockSize() throws IOException {
            * @throws  IOException
            *          if an I/O error occurs
            */
      -    public abstract Object getAttribute(String attribute) throws IOException;
      +    public abstract @Nullable Object getAttribute(String attribute) throws IOException;
       }
      diff --git a/src/java.base/share/classes/java/nio/file/FileSystems.java b/src/java.base/share/classes/java/nio/file/FileSystems.java
      index 79515314660..bf8c6b88c25 100644
      --- a/src/java.base/share/classes/java/nio/file/FileSystems.java
      +++ b/src/java.base/share/classes/java/nio/file/FileSystems.java
      @@ -28,6 +28,7 @@
       import org.checkerframework.checker.interning.qual.UsesObjectEquals;
       import org.checkerframework.checker.nullness.qual.Nullable;
       import org.checkerframework.framework.qual.AnnotatedFor;
      +import org.checkerframework.checker.nullness.qual.Nullable;
       
       import java.nio.file.spi.FileSystemProvider;
       import java.net.URI;
      diff --git a/src/java.base/share/classes/java/nio/file/FileVisitor.java b/src/java.base/share/classes/java/nio/file/FileVisitor.java
      index 5c555ae77e1..fe0816059ef 100644
      --- a/src/java.base/share/classes/java/nio/file/FileVisitor.java
      +++ b/src/java.base/share/classes/java/nio/file/FileVisitor.java
      @@ -28,6 +28,9 @@
       import java.nio.file.attribute.BasicFileAttributes;
       import java.io.IOException;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * A visitor of files. An implementation of this interface is provided to the
        * {@link Files#walkFileTree Files.walkFileTree} methods to visit each file in
      @@ -95,6 +98,7 @@
        * @since 1.7
        */
       
      +@AnnotatedFor({"nullness"})
       public interface FileVisitor {
       
           /**
      @@ -172,6 +176,6 @@ FileVisitResult visitFileFailed(T file, IOException exc)
            * @throws  IOException
            *          if an I/O error occurs
            */
      -    FileVisitResult postVisitDirectory(T dir, IOException exc)
      +    FileVisitResult postVisitDirectory(T dir, @Nullable IOException exc)
               throws IOException;
       }
      diff --git a/src/java.base/share/classes/java/nio/file/LinkPermission.java b/src/java.base/share/classes/java/nio/file/LinkPermission.java
      index 81921f059cb..f102eae2670 100644
      --- a/src/java.base/share/classes/java/nio/file/LinkPermission.java
      +++ b/src/java.base/share/classes/java/nio/file/LinkPermission.java
      @@ -27,6 +27,9 @@
       
       import java.security.BasicPermission;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * The {@code Permission} class for link creation operations.
        *
      @@ -66,6 +69,8 @@
        * @see Files#createLink
        * @see Files#createSymbolicLink
        */
      +
      +@AnnotatedFor({"nullness"})
       public final class LinkPermission extends BasicPermission {
           @java.io.Serial
           static final long serialVersionUID = -1441492453772213220L;
      @@ -102,7 +107,7 @@ public LinkPermission(String name) {
            * @throws  IllegalArgumentException
            *          if name is empty or invalid, or actions is a non-empty string
            */
      -    public LinkPermission(String name, String actions) {
      +    public LinkPermission(String name, @Nullable String actions) {
               super(name);
               checkName(name);
               if (actions != null && !actions.isEmpty()) {
      diff --git a/src/java.base/share/classes/java/nio/file/SecureDirectoryStream.java b/src/java.base/share/classes/java/nio/file/SecureDirectoryStream.java
      index 8cfaea35f4a..f04d5b47a65 100644
      --- a/src/java.base/share/classes/java/nio/file/SecureDirectoryStream.java
      +++ b/src/java.base/share/classes/java/nio/file/SecureDirectoryStream.java
      @@ -29,6 +29,9 @@
       import java.util.Set;
       import java.io.IOException;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * A {@code DirectoryStream} that defines operations on files that are located
        * relative to an open directory. A {@code SecureDirectoryStream} is intended
      @@ -56,6 +59,8 @@
        * @since   1.7
        */
       
      +@AnnotatedFor({"nullness"})
      +
       public interface SecureDirectoryStream
           extends DirectoryStream
       {
      @@ -271,7 +276,7 @@ void move(T srcpath, SecureDirectoryStream targetdir, T targetpath)
            *          this directory stream, or {@code null} if the attribute view
            *          type is not available
            */
      -     V getFileAttributeView(Class type);
      +     @Nullable V getFileAttributeView(Class type);
       
           /**
            * Returns a new file attribute view to access the file attributes of a file
      @@ -306,7 +311,7 @@ void move(T srcpath, SecureDirectoryStream targetdir, T targetpath)
            *          type is not available
            *
            */
      -     V getFileAttributeView(T path,
      +     @Nullable V getFileAttributeView(T path,
                                                                Class type,
                                                                LinkOption... options);
       }
      diff --git a/src/java.base/share/classes/java/nio/file/SimpleFileVisitor.java b/src/java.base/share/classes/java/nio/file/SimpleFileVisitor.java
      index b4e9713c8e5..d9dacce1270 100644
      --- a/src/java.base/share/classes/java/nio/file/SimpleFileVisitor.java
      +++ b/src/java.base/share/classes/java/nio/file/SimpleFileVisitor.java
      @@ -26,6 +26,7 @@
       package java.nio.file;
       
       import org.checkerframework.checker.interning.qual.UsesObjectEquals;
      +import org.checkerframework.checker.nullness.qual.Nullable;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.nio.file.attribute.BasicFileAttributes;
      @@ -43,7 +44,7 @@
        * @since 1.7
        */
       
      -@AnnotatedFor({"interning"})
      +@AnnotatedFor({"interning", "nullness"})
       public @UsesObjectEquals class SimpleFileVisitor implements FileVisitor {
           /**
            * Initializes a new instance of this class.
      @@ -105,7 +106,7 @@ public FileVisitResult visitFileFailed(T file, IOException exc)
            * of the directory to terminate prematurely.
            */
           @Override
      -    public FileVisitResult postVisitDirectory(T dir, IOException exc)
      +    public FileVisitResult postVisitDirectory(T dir, @Nullable IOException exc)
               throws IOException
           {
               Objects.requireNonNull(dir);
      diff --git a/src/java.base/share/classes/java/nio/file/WatchEvent.java b/src/java.base/share/classes/java/nio/file/WatchEvent.java
      index 25438a86f9a..e71fc710d88 100644
      --- a/src/java.base/share/classes/java/nio/file/WatchEvent.java
      +++ b/src/java.base/share/classes/java/nio/file/WatchEvent.java
      @@ -25,6 +25,9 @@
       
       package java.nio.file;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * An event or a repeated event for an object that is registered with a {@link
        * WatchService}.
      @@ -44,7 +47,8 @@
        * @since 1.7
        */
       
      -public interface WatchEvent {
      +@AnnotatedFor({"nullness"})
      +public interface WatchEvent {
       
           /**
            * An event kind, for the purposes of identification.
      @@ -52,7 +56,7 @@ public interface WatchEvent {
            * @since 1.7
            * @see StandardWatchEventKinds
            */
      -    public static interface Kind {
      +    public static interface Kind {
               /**
                * Returns the name of the event kind.
                *
      diff --git a/src/java.base/share/classes/java/nio/file/WatchService.java b/src/java.base/share/classes/java/nio/file/WatchService.java
      index 042df2458f0..2b5961571ee 100644
      --- a/src/java.base/share/classes/java/nio/file/WatchService.java
      +++ b/src/java.base/share/classes/java/nio/file/WatchService.java
      @@ -31,6 +31,7 @@
       
       import org.checkerframework.checker.mustcall.qual.InheritableMustCall;
       import org.checkerframework.framework.qual.AnnotatedFor;
      +import org.checkerframework.checker.nullness.qual.Nullable;
       
       /**
        * A watch service that watches registered objects for changes and
      @@ -105,7 +106,7 @@
        *
        * @see FileSystem#newWatchService
        */
      -@AnnotatedFor({"mustcall"})
      +@AnnotatedFor({"mustcall", "nullness"})
       @InheritableMustCall({})
       public interface WatchService
           extends Closeable
      @@ -140,7 +141,7 @@ public interface WatchService
            * @throws  ClosedWatchServiceException
            *          if this watch service is closed
            */
      -    WatchKey poll();
      +    @Nullable WatchKey poll();
       
           /**
            * Retrieves and removes the next watch key, waiting if necessary up to the
      @@ -160,7 +161,7 @@ public interface WatchService
            * @throws  InterruptedException
            *          if interrupted while waiting
            */
      -    WatchKey poll(long timeout, TimeUnit unit)
      +    @Nullable WatchKey poll(long timeout, TimeUnit unit)
               throws InterruptedException;
       
           /**
      diff --git a/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributeView.java b/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributeView.java
      index 57c4aa9539d..f753800949d 100644
      --- a/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributeView.java
      +++ b/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributeView.java
      @@ -30,6 +30,9 @@
       
       import java.io.IOException;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.framework.qual.AnnotatedFor;
      +
       /**
        * A file attribute view that provides a view of a basic set of file
        * attributes common to many file systems. The basic set of file attributes
      diff --git a/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributes.java b/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributes.java
      index 2c20c09df88..712fe7c31f4 100644
      --- a/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributes.java
      +++ b/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributes.java
      @@ -27,6 +27,7 @@
       
       import org.checkerframework.checker.index.qual.NonNegative;
       import org.checkerframework.framework.qual.AnnotatedFor;
      +import org.checkerframework.checker.nullness.qual.Nullable;
       
       /**
        * Basic attributes associated with a file in a file system.
      @@ -46,7 +47,7 @@
        * @see BasicFileAttributeView
        */
       
      -@AnnotatedFor({"index"})
      +@AnnotatedFor({"index", "nullness"})
       public interface BasicFileAttributes {
       
           /**
      @@ -155,5 +156,5 @@ public interface BasicFileAttributes {
            *
            * @see java.nio.file.Files#walkFileTree
            */
      -    Object fileKey();
      +    @Nullable Object fileKey();
       }
      diff --git a/src/java.base/share/classes/java/nio/file/spi/FileSystemProvider.java b/src/java.base/share/classes/java/nio/file/spi/FileSystemProvider.java
      index 5f1741f1f37..90ec81611ad 100644
      --- a/src/java.base/share/classes/java/nio/file/spi/FileSystemProvider.java
      +++ b/src/java.base/share/classes/java/nio/file/spi/FileSystemProvider.java
      @@ -26,6 +26,7 @@
       package java.nio.file.spi;
       
       import org.checkerframework.checker.interning.qual.UsesObjectEquals;
      +import org.checkerframework.checker.nullness.qual.Nullable;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.nio.channels.AsynchronousFileChannel;
      @@ -113,7 +114,7 @@
        * @since 1.7
        */
       
      -@AnnotatedFor({"interning"})
      +@AnnotatedFor({"interning", "nullness"})
       public abstract @UsesObjectEquals class FileSystemProvider {
           // lock using when loading providers
           private static final Object lock = new Object();
      @@ -586,7 +587,7 @@ public FileChannel newFileChannel(Path path,
            */
           public AsynchronousFileChannel newAsynchronousFileChannel(Path path,
                                                                     Set options,
      -                                                              ExecutorService executor,
      +                                                              @Nullable ExecutorService executor,
                                                                     FileAttribute... attrs)
               throws IOException
           {
      @@ -1074,7 +1075,7 @@ public abstract void checkAccess(Path path, AccessMode... modes)
            * @return  a file attribute view of the specified type, or {@code null} if
            *          the attribute view type is not available
            */
      -    public abstract  V
      +    public abstract  V
               getFileAttributeView(Path path, Class type, LinkOption... options);
       
           /**
      diff --git a/src/java.base/share/classes/java/nio/file/spi/FileTypeDetector.java b/src/java.base/share/classes/java/nio/file/spi/FileTypeDetector.java
      index 5c64c267ec1..29dac692d49 100644
      --- a/src/java.base/share/classes/java/nio/file/spi/FileTypeDetector.java
      +++ b/src/java.base/share/classes/java/nio/file/spi/FileTypeDetector.java
      @@ -25,6 +25,7 @@
       
       package java.nio.file.spi;
       
      +import org.checkerframework.checker.nullness.qual.Nullable;
       import org.checkerframework.checker.interning.qual.UsesObjectEquals;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
      @@ -50,7 +51,7 @@
        * @since 1.7
        */
       
      -@AnnotatedFor({"interning"})
      +@AnnotatedFor({"interning", "nullable"})
       public abstract @UsesObjectEquals class FileTypeDetector {
       
           private static Void checkPermission() {
      @@ -106,6 +107,6 @@ protected FileTypeDetector() {
            *
            * @see java.nio.file.Files#probeContentType
            */
      -    public abstract String probeContentType(Path path)
      +    public abstract @Nullable String probeContentType(Path path)
               throws IOException;
       }
      
      From 060aa243dd39094c55cba00a23aa9ce722c8392e Mon Sep 17 00:00:00 2001
      From: Michael Ernst 
      Date: Wed, 26 Nov 2025 21:43:13 -0800
      Subject: [PATCH 75/82] Write `@Identifier` on `Method.getName()`
      
      ---
       src/java.base/share/classes/java/lang/reflect/Method.java | 3 ++-
       1 file changed, 2 insertions(+), 1 deletion(-)
      
      diff --git a/src/java.base/share/classes/java/lang/reflect/Method.java b/src/java.base/share/classes/java/lang/reflect/Method.java
      index a1d7fbd653a..652f513ba0d 100644
      --- a/src/java.base/share/classes/java/lang/reflect/Method.java
      +++ b/src/java.base/share/classes/java/lang/reflect/Method.java
      @@ -28,6 +28,7 @@
       import org.checkerframework.checker.interning.qual.Interned;
       import org.checkerframework.checker.lock.qual.GuardSatisfied;
       import org.checkerframework.checker.nullness.qual.Nullable;
      +import org.checkerframework.checker.signature.qual.Identifier;
       import org.checkerframework.common.reflection.qual.Invoke;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      @@ -239,7 +240,7 @@ public Class getDeclaringClass() {
            * object, as a {@code String}.
            */
           @Override
      -    public @Interned String getName() {
      +    public @Interned @Identifier String getName() {
               return name;
           }
       
      
      From 326b484edea6defc638e93b4991d61743a0b2ed0 Mon Sep 17 00:00:00 2001
      From: Michael Ernst 
      Date: Fri, 28 Nov 2025 16:39:50 -0800
      Subject: [PATCH 76/82] Add `@Identifier` in `StackTraceElement`
      
      ---
       .../share/classes/java/lang/StackTraceElement.java         | 7 ++++---
       1 file changed, 4 insertions(+), 3 deletions(-)
      
      diff --git a/src/java.base/share/classes/java/lang/StackTraceElement.java b/src/java.base/share/classes/java/lang/StackTraceElement.java
      index 27b5bd237a2..37700f4e172 100644
      --- a/src/java.base/share/classes/java/lang/StackTraceElement.java
      +++ b/src/java.base/share/classes/java/lang/StackTraceElement.java
      @@ -28,6 +28,7 @@
       import org.checkerframework.checker.lock.qual.GuardSatisfied;
       import org.checkerframework.checker.nullness.qual.Nullable;
       import org.checkerframework.checker.signature.qual.FullyQualifiedName;
      +import org.checkerframework.checker.signature.qual.Identifier;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
       import org.checkerframework.framework.qual.AnnotatedFor;
      @@ -124,7 +125,7 @@ public final class StackTraceElement implements java.io.Serializable {
            * @since 1.5
            * @revised 9
            */
      -    public StackTraceElement(@FullyQualifiedName String declaringClass, String methodName,
      +    public StackTraceElement(@FullyQualifiedName String declaringClass, @Identifier String methodName,
                                    @Nullable String fileName, int lineNumber) {
               this(null, null, null, declaringClass, methodName, fileName, lineNumber);
           }
      @@ -162,7 +163,7 @@ public StackTraceElement(@FullyQualifiedName String declaringClass, String metho
            */
           public StackTraceElement(String classLoaderName,
                                    String moduleName, String moduleVersion,
      -                             String declaringClass, String methodName,
      +                             String declaringClass, @Identifier String methodName,
                                    String fileName, int lineNumber) {
               this.classLoaderName = classLoaderName;
               this.moduleName      = moduleName;
      @@ -275,7 +276,7 @@ public String getClassLoaderName() {
            * @return the name of the method containing the execution point
            *         represented by this stack trace element.
            */
      -    public String getMethodName(@GuardSatisfied StackTraceElement this) {
      +    public @Identifier String getMethodName(@GuardSatisfied StackTraceElement this) {
               return methodName;
           }
       
      
      From 23e9f39cf7be05e16b5faee019f3076087c52b6d Mon Sep 17 00:00:00 2001
      From: Michael Ernst 
      Date: Mon, 1 Dec 2025 12:12:40 -0800
      Subject: [PATCH 77/82] More signature annotations
      
      ---
       src/java.base/share/classes/java/lang/constant/ClassDesc.java | 4 +++-
       .../share/classes/java/lang/constant/MethodTypeDesc.java      | 4 +++-
       2 files changed, 6 insertions(+), 2 deletions(-)
      
      diff --git a/src/java.base/share/classes/java/lang/constant/ClassDesc.java b/src/java.base/share/classes/java/lang/constant/ClassDesc.java
      index 435d992fa50..2178151f1ce 100644
      --- a/src/java.base/share/classes/java/lang/constant/ClassDesc.java
      +++ b/src/java.base/share/classes/java/lang/constant/ClassDesc.java
      @@ -24,6 +24,8 @@
        */
       package java.lang.constant;
       
      +import org.checkerframework.checker.signature.qual.FieldDescriptor;
      +
       import java.lang.invoke.TypeDescriptor;
       import java.util.stream.Stream;
       
      @@ -316,7 +318,7 @@ else if (isArray()) {
            * @return the descriptor string
            * @jvms 4.3.2 Field Descriptors
            */
      -    String descriptorString();
      +    @FieldDescriptor String descriptorString();
       
           /**
            * Compare the specified object with this descriptor for equality.  Returns
      diff --git a/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java b/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java
      index 4750231ce37..48216343184 100644
      --- a/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java
      +++ b/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java
      @@ -24,6 +24,8 @@
        */
       package java.lang.constant;
       
      +import org.checkerframework.checker.signature.qual.MethodDescriptor;
      +
       import java.lang.invoke.MethodType;
       import java.lang.invoke.TypeDescriptor;
       import java.util.List;
      @@ -166,7 +168,7 @@ static MethodTypeDesc of(ClassDesc returnDesc, ClassDesc... paramDescs) {
            * @return the method type descriptor string
            * @jvms 4.3.3 Method Descriptors
            */
      -    default String descriptorString() {
      +    default @MethodDescriptor String descriptorString() {
               return String.format("(%s)%s",
                                    Stream.of(parameterArray())
                                          .map(ClassDesc::descriptorString)
      
      From a6fca33db93284cfcb5ed701b37456b31464d8b0 Mon Sep 17 00:00:00 2001
      From: Werner Dietl 
      Date: Fri, 2 Oct 2026 00:11:19 -0400
      Subject: [PATCH 78/82] Remove the @SideEffectsOnly annotations
      
      The Checker Framework does not have the @SideEffectsOnly qualifier (it comes
      from typetools' Side Effects Only Checker work), and the master branch of this
      repository does not use it.  An annotated JDK file that uses an unknown
      annotation is ignored in its entirety, and the binary stub generator cannot read
      the qualifier, so remove the qualifier and its 94 uses, as in master.
      
      Co-Authored-By: Claude Sonnet 5.5 
      ---
       .../share/classes/java/io/BufferedReader.java |  2 --
       .../share/classes/java/lang/CharSequence.java |  3 --
       .../classes/java/lang/StackStreamFactory.java |  2 --
       .../classes/java/lang/StringBuilder.java      | 31 -------------------
       .../lang/invoke/AbstractConstantGroup.java    |  2 --
       src/java.base/share/classes/java/net/URL.java |  2 --
       .../classes/java/nio/charset/Charset.java     |  2 --
       .../java/nio/file/FileTreeIterator.java       |  2 --
       .../share/classes/java/nio/file/Files.java    |  2 --
       .../share/classes/java/nio/file/Path.java     |  2 --
       .../share/classes/java/util/AbstractList.java |  4 ---
       .../share/classes/java/util/AbstractMap.java  |  3 --
       .../share/classes/java/util/ArrayDeque.java   |  2 --
       .../share/classes/java/util/ArrayList.java    |  9 ------
       .../share/classes/java/util/Arrays.java       |  2 --
       .../share/classes/java/util/Collections.java  | 10 ------
       .../share/classes/java/util/EnumMap.java      |  1 -
       .../share/classes/java/util/Enumeration.java  |  2 --
       .../share/classes/java/util/HashMap.java      |  2 --
       .../share/classes/java/util/HashSet.java      |  4 ---
       .../share/classes/java/util/Hashtable.java    |  2 --
       .../classes/java/util/IdentityHashMap.java    |  2 --
       .../java/util/ImmutableCollections.java       |  5 ---
       .../share/classes/java/util/Iterator.java     |  2 --
       .../share/classes/java/util/JumboEnumSet.java |  2 --
       .../classes/java/util/LinkedHashMap.java      |  2 --
       .../share/classes/java/util/LinkedList.java   |  3 --
       .../share/classes/java/util/List.java         |  6 ----
       .../share/classes/java/util/ListIterator.java |  2 --
       .../classes/java/util/PriorityQueue.java      |  2 --
       .../classes/java/util/RegularEnumSet.java     |  2 --
       .../share/classes/java/util/Scanner.java      | 19 ------------
       .../classes/java/util/ServiceLoader.java      |  5 ---
       .../share/classes/java/util/Spliterators.java |  5 ---
       .../share/classes/java/util/TreeMap.java      |  5 ---
       .../share/classes/java/util/Vector.java       |  3 --
       .../share/classes/java/util/WeakHashMap.java  |  2 --
       .../util/concurrent/ArrayBlockingQueue.java   |  2 --
       .../util/concurrent/ConcurrentHashMap.java    |  1 -
       .../concurrent/ConcurrentLinkedDeque.java     |  2 --
       .../concurrent/ConcurrentLinkedQueue.java     |  2 --
       .../concurrent/ConcurrentSkipListMap.java     |  1 -
       .../util/concurrent/CopyOnWriteArrayList.java |  4 ---
       .../java/util/concurrent/DelayQueue.java      |  2 --
       .../util/concurrent/LinkedBlockingDeque.java  |  2 --
       .../util/concurrent/LinkedBlockingQueue.java  |  2 --
       .../util/concurrent/LinkedTransferQueue.java  |  2 --
       .../concurrent/PriorityBlockingQueue.java     |  2 --
       .../ScheduledThreadPoolExecutor.java          |  2 --
       .../classes/java/util/regex/Matcher.java      |  2 --
       .../classes/java/util/regex/Pattern.java      |  2 --
       .../share/classes/java/util/zip/ZipFile.java  |  3 --
       .../classes/javax/security/auth/Subject.java  |  2 --
       .../dataflow/qual/SideEffectsOnly.java        | 29 -----------------
       .../classes/sun/net/www/HeaderParser.java     |  2 --
       .../classes/sun/net/www/MessageHeader.java    |  2 --
       .../sun/security/jca/ProviderList.java        |  2 --
       .../share/classes/sun/util/PreHashedMap.java  |  3 --
       .../sun/util/locale/StringTokenIterator.java  |  2 --
       .../resources/ParallelListResourceBundle.java |  2 --
       .../classes/java/lang/ProcessEnvironment.java |  4 ---
       .../sun/nio/fs/UnixDirectoryStream.java       |  2 --
       .../classes/sun/nio/fs/UnixFileSystem.java    |  2 --
       .../classes/java/lang/ProcessEnvironment.java |  2 --
       .../sun/nio/fs/WindowsDirectoryStream.java    |  2 --
       .../classes/sun/nio/fs/WindowsFileSystem.java |  2 --
       .../counter/perf/PerfInstrumentation.java     |  2 --
       .../jdk/internal/net/http/HeaderParser.java   |  2 --
       .../internal/net/http/RequestPublishers.java  |  3 --
       .../share/classes/java/sql/SQLException.java  |  2 --
       .../keys/keyresolver/KeyResolver.java         |  2 --
       .../keys/storage/StorageResolver.java         |  2 --
       .../implementations/KeyStoreResolver.java     |  2 --
       .../SingleCertificateResolver.java            |  2 --
       .../security/signature/Reference.java         |  2 --
       .../reference/ReferenceSubTreeData.java       |  2 --
       .../xml/dsig/internal/dom/DOMSubTreeData.java |  2 --
       .../internal/generic/InstructionList.java     |  1 -
       .../internal/impl/XMLStreamFilterImpl.java    |  2 --
       .../internal/impl/XMLStreamReaderImpl.java    |  1 -
       .../xerces/internal/impl/xs/XSModelImpl.java  |  2 --
       .../internal/impl/xs/util/XSNamedMapImpl.java |  2 --
       .../impl/xs/util/XSObjectListImpl.java        |  3 --
       .../internal/util/NamespaceSupport.java       |  2 --
       .../util/XMLAttributesIteratorImpl.java       |  2 --
       .../xpath/internal/jaxp/XPathNodesImpl.java   |  2 --
       .../internal/stream/EventFilterSupport.java   |  2 --
       .../internal/stream/XMLEventReaderImpl.java   |  2 --
       .../stream/util/ReadOnlyIterator.java         |  2 --
       .../javax/xml/catalog/CatalogImpl.java        |  2 --
       .../javax/xml/stream/XMLEventReader.java      |  2 --
       .../javax/xml/stream/XMLStreamReader.java     |  2 --
       .../xml/stream/util/EventReaderDelegate.java  |  2 --
       .../xml/stream/util/StreamReaderDelegate.java |  1 -
       .../nio/cs/ext/AbstractCharsetProvider.java   |  2 --
       95 files changed, 304 deletions(-)
       delete mode 100644 src/java.base/share/classes/org/checkerframework/dataflow/qual/SideEffectsOnly.java
      
      diff --git a/src/java.base/share/classes/java/io/BufferedReader.java b/src/java.base/share/classes/java/io/BufferedReader.java
      index d2b1c6feda5..0d6078cbe62 100644
      --- a/src/java.base/share/classes/java/io/BufferedReader.java
      +++ b/src/java.base/share/classes/java/io/BufferedReader.java
      @@ -38,7 +38,6 @@
       import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
       import org.checkerframework.checker.nullness.qual.Nullable;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.util.Iterator;
      @@ -708,7 +707,6 @@ public boolean hasNext() {
                   }
       
                   @Override
      -            @SideEffectsOnly("this")
                   public String next(/*@NonEmpty Iterator this*/) {
                       if (nextLine != null || hasNext()) {
                           String line = nextLine;
      diff --git a/src/java.base/share/classes/java/lang/CharSequence.java b/src/java.base/share/classes/java/lang/CharSequence.java
      index e79f030b6ed..6205b94885a 100644
      --- a/src/java.base/share/classes/java/lang/CharSequence.java
      +++ b/src/java.base/share/classes/java/lang/CharSequence.java
      @@ -34,7 +34,6 @@
       import org.checkerframework.checker.nonempty.qual.NonEmpty;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.util.NoSuchElementException;
      @@ -174,7 +173,6 @@ public boolean hasNext() {
                       return cur < length();
                   }
       
      -            @SideEffectsOnly("this")
                   public int nextInt(@NonEmpty CharIterator this) {
                       if (hasNext()) {
                           return charAt(cur++);
      @@ -251,7 +249,6 @@ public boolean hasNext() {
                       return cur < length();
                   }
       
      -            @SideEffectsOnly("this")
                   public int nextInt(@NonEmpty CodePointIterator this) {
                       final int length = length();
       
      diff --git a/src/java.base/share/classes/java/lang/StackStreamFactory.java b/src/java.base/share/classes/java/lang/StackStreamFactory.java
      index 2900a4f31ce..37fb1188aea 100644
      --- a/src/java.base/share/classes/java/lang/StackStreamFactory.java
      +++ b/src/java.base/share/classes/java/lang/StackStreamFactory.java
      @@ -26,7 +26,6 @@
       
       import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import jdk.internal.reflect.MethodAccessor;
       import jdk.internal.reflect.ConstructorAccessor;
       import java.lang.StackWalker.Option;
      @@ -375,7 +374,6 @@ private void setContinuation(Continuation cont) {
                *
                * @see #tryNextFrame
                */
      -        @SideEffectsOnly("this")
               final Class nextFrame() {
                   if (!hasNext()) {
                       return null;
      diff --git a/src/java.base/share/classes/java/lang/StringBuilder.java b/src/java.base/share/classes/java/lang/StringBuilder.java
      index 9647c26c330..1629830aecf 100644
      --- a/src/java.base/share/classes/java/lang/StringBuilder.java
      +++ b/src/java.base/share/classes/java/lang/StringBuilder.java
      @@ -34,7 +34,6 @@
       import org.checkerframework.checker.regex.qual.PolyRegex;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import jdk.internal.vm.annotation.IntrinsicCandidate;
      @@ -182,14 +181,12 @@ public int compareTo(StringBuilder another) {
           }
       
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder append(@GuardSatisfied @Nullable Object obj) {
               return append(String.valueOf(obj));
           }
       
           @Override
           @IntrinsicCandidate
      -    @SideEffectsOnly("this")
           public StringBuilder append(@Nullable String str) {
               super.append(str);
               return this;
      @@ -214,14 +211,12 @@ public StringBuilder append(@Nullable String str) {
            * @param   sb   the {@code StringBuffer} to append.
            * @return  a reference to this object.
            */
      -    @SideEffectsOnly("this")
           public StringBuilder append(@Nullable StringBuffer sb) {
               super.append(sb);
               return this;
           }
       
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder append(@Nullable CharSequence s) {
               super.append(s);
               return this;
      @@ -231,14 +226,12 @@ public StringBuilder append(@Nullable CharSequence s) {
            * @throws     IndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder append(@Nullable CharSequence s, @IndexOrHigh({"#1"}) int start, @IndexOrHigh({"#1"}) int end) {
               super.append(s, start, end);
               return this;
           }
       
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder append(char[] str) {
               super.append(str);
               return this;
      @@ -248,14 +241,12 @@ public StringBuilder append(char[] str) {
            * @throws IndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder append(char[] str, @IndexOrHigh({"#1"}) int offset, @LTLengthOf(value={"#1"}, offset={"#2 - 1"}) @NonNegative int len) {
               super.append(str, offset, len);
               return this;
           }
       
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder append(boolean b) {
               super.append(b);
               return this;
      @@ -263,7 +254,6 @@ public StringBuilder append(boolean b) {
       
           @Override
           @IntrinsicCandidate
      -    @SideEffectsOnly("this")
           public StringBuilder append(char c) {
               super.append(c);
               return this;
      @@ -271,28 +261,24 @@ public StringBuilder append(char c) {
       
           @Override
           @IntrinsicCandidate
      -    @SideEffectsOnly("this")
           public StringBuilder append(int i) {
               super.append(i);
               return this;
           }
       
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder append(long lng) {
               super.append(lng);
               return this;
           }
       
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder append(float f) {
               super.append(f);
               return this;
           }
       
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder append(double d) {
               super.append(d);
               return this;
      @@ -302,7 +288,6 @@ public StringBuilder append(double d) {
            * @since 1.5
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder appendCodePoint(int codePoint) {
               super.appendCodePoint(codePoint);
               return this;
      @@ -312,7 +297,6 @@ public StringBuilder appendCodePoint(int codePoint) {
            * @throws StringIndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder delete(@NonNegative int start, @NonNegative int end) {
               super.delete(start, end);
               return this;
      @@ -322,7 +306,6 @@ public StringBuilder delete(@NonNegative int start, @NonNegative int end) {
            * @throws StringIndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder deleteCharAt(@NonNegative int index) {
               super.deleteCharAt(index);
               return this;
      @@ -332,7 +315,6 @@ public StringBuilder deleteCharAt(@NonNegative int index) {
            * @throws StringIndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder replace(@NonNegative int start, @NonNegative int end, String str) {
               super.replace(start, end, str);
               return this;
      @@ -342,7 +324,6 @@ public StringBuilder replace(@NonNegative int start, @NonNegative int end, Strin
            * @throws StringIndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder insert(@NonNegative int index, char[] str, @IndexOrHigh({"#2"}) int offset,
                                       @IndexOrHigh({"#2"}) int len)
           {
      @@ -354,7 +335,6 @@ public StringBuilder insert(@NonNegative int index, char[] str, @IndexOrHigh({"#
            * @throws StringIndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder insert(@NonNegative int offset, @GuardSatisfied @Nullable Object obj) {
                   super.insert(offset, obj);
                   return this;
      @@ -364,7 +344,6 @@ public StringBuilder insert(@NonNegative int offset, @GuardSatisfied @Nullable O
            * @throws StringIndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder insert(@NonNegative int offset, @Nullable String str) {
               super.insert(offset, str);
               return this;
      @@ -374,7 +353,6 @@ public StringBuilder insert(@NonNegative int offset, @Nullable String str) {
            * @throws StringIndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder insert(@NonNegative int offset, char[] str) {
               super.insert(offset, str);
               return this;
      @@ -384,7 +362,6 @@ public StringBuilder insert(@NonNegative int offset, char[] str) {
            * @throws IndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder insert(@NonNegative int dstOffset, @Nullable CharSequence s) {
                   super.insert(dstOffset, s);
                   return this;
      @@ -394,7 +371,6 @@ public StringBuilder insert(@NonNegative int dstOffset, @Nullable CharSequence s
            * @throws IndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder insert(@NonNegative int dstOffset, @Nullable CharSequence s,
                                       @NonNegative int start, @NonNegative int end)
           {
      @@ -406,7 +382,6 @@ public StringBuilder insert(@NonNegative int dstOffset, @Nullable CharSequence s
            * @throws StringIndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder insert(@NonNegative int offset, boolean b) {
               super.insert(offset, b);
               return this;
      @@ -416,7 +391,6 @@ public StringBuilder insert(@NonNegative int offset, boolean b) {
            * @throws IndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder insert(@NonNegative int offset, char c) {
               super.insert(offset, c);
               return this;
      @@ -426,7 +400,6 @@ public StringBuilder insert(@NonNegative int offset, char c) {
            * @throws StringIndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder insert(@NonNegative int offset, int i) {
               super.insert(offset, i);
               return this;
      @@ -436,7 +409,6 @@ public StringBuilder insert(@NonNegative int offset, int i) {
            * @throws StringIndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder insert(@NonNegative int offset, long l) {
               super.insert(offset, l);
               return this;
      @@ -446,7 +418,6 @@ public StringBuilder insert(@NonNegative int offset, long l) {
            * @throws StringIndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder insert(@NonNegative int offset, float f) {
               super.insert(offset, f);
               return this;
      @@ -456,7 +427,6 @@ public StringBuilder insert(@NonNegative int offset, float f) {
            * @throws StringIndexOutOfBoundsException {@inheritDoc}
            */
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder insert(@NonNegative int offset, double d) {
               super.insert(offset, d);
               return this;
      @@ -487,7 +457,6 @@ public StringBuilder insert(@NonNegative int offset, double d) {
           }
       
           @Override
      -    @SideEffectsOnly("this")
           public StringBuilder reverse() {
               super.reverse();
               return this;
      diff --git a/src/java.base/share/classes/java/lang/invoke/AbstractConstantGroup.java b/src/java.base/share/classes/java/lang/invoke/AbstractConstantGroup.java
      index 1863d17c082..58661dcd5c0 100644
      --- a/src/java.base/share/classes/java/lang/invoke/AbstractConstantGroup.java
      +++ b/src/java.base/share/classes/java/lang/invoke/AbstractConstantGroup.java
      @@ -28,7 +28,6 @@
       import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf;
       import org.checkerframework.checker.nonempty.qual.NonEmpty;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.util.*;
       import jdk.internal.vm.annotation.Stable;
      @@ -100,7 +99,6 @@ public boolean hasNext() {
               }
       
               @Override
      -        @SideEffectsOnly("this")
               public Object next(@NonEmpty AsIterator this) {
                   int i = bumpIndex();
                   if (resolving)
      diff --git a/src/java.base/share/classes/java/net/URL.java b/src/java.base/share/classes/java/net/URL.java
      index 56c7f6c8496..1b393cf871c 100644
      --- a/src/java.base/share/classes/java/net/URL.java
      +++ b/src/java.base/share/classes/java/net/URL.java
      @@ -33,7 +33,6 @@
       import org.checkerframework.checker.nullness.qual.Nullable;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.io.File;
      @@ -1512,7 +1511,6 @@ public boolean hasNext() {
                       return getNext();
                   }
       
      -            @SideEffectsOnly("this")
                   public URLStreamHandlerProvider next(/*@NonEmpty Iterator this*/) {
                       if (!getNext())
                           throw new NoSuchElementException();
      diff --git a/src/java.base/share/classes/java/nio/charset/Charset.java b/src/java.base/share/classes/java/nio/charset/Charset.java
      index 5cb2e1a6dfc..7ee6a477c10 100644
      --- a/src/java.base/share/classes/java/nio/charset/Charset.java
      +++ b/src/java.base/share/classes/java/nio/charset/Charset.java
      @@ -28,7 +28,6 @@
       import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf;
       import org.checkerframework.checker.nonempty.qual.NonEmpty;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import jdk.internal.misc.ThreadTracker;
       import jdk.internal.misc.VM;
      @@ -370,7 +369,6 @@ public boolean hasNext() {
                           return getNext();
                       }
       
      -                @SideEffectsOnly("this")
                       public CharsetProvider next(/*@NonEmpty Iterator this*/) {
                           if (!getNext())
                               throw new NoSuchElementException();
      diff --git a/src/java.base/share/classes/java/nio/file/FileTreeIterator.java b/src/java.base/share/classes/java/nio/file/FileTreeIterator.java
      index 1015bb8f2c1..5e6442f0a92 100644
      --- a/src/java.base/share/classes/java/nio/file/FileTreeIterator.java
      +++ b/src/java.base/share/classes/java/nio/file/FileTreeIterator.java
      @@ -28,7 +28,6 @@
       import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf;
       import org.checkerframework.checker.nonempty.qual.NonEmpty;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.io.Closeable;
       import java.io.IOException;
      @@ -112,7 +111,6 @@ public boolean hasNext() {
           }
       
           @Override
      -    @SideEffectsOnly("this")
           public Event next(@NonEmpty FileTreeIterator this) {
               if (!walker.isOpen())
                   throw new IllegalStateException();
      diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java
      index 7b81486be54..aea66063a86 100644
      --- a/src/java.base/share/classes/java/nio/file/Files.java
      +++ b/src/java.base/share/classes/java/nio/file/Files.java
      @@ -34,7 +34,6 @@
       import org.checkerframework.checker.signedness.qual.PolySigned;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.checker.nullness.qual.Nullable;
       
      @@ -3868,7 +3867,6 @@ public boolean hasNext() {
                               throw new UncheckedIOException(e.getCause());
                           }
                       }
      -                @SideEffectsOnly("this")
                       @Override
                       public Path next(/*@NonEmpty Iterator this*/) {
                           try {
      diff --git a/src/java.base/share/classes/java/nio/file/Path.java b/src/java.base/share/classes/java/nio/file/Path.java
      index a5e263acdae..aea2a499b13 100644
      --- a/src/java.base/share/classes/java/nio/file/Path.java
      +++ b/src/java.base/share/classes/java/nio/file/Path.java
      @@ -30,7 +30,6 @@
       import org.checkerframework.checker.nullness.qual.Nullable;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.io.File;
      @@ -962,7 +961,6 @@ public boolean hasNext() {
                   }
       
                   @Override
      -            @SideEffectsOnly("this")
                   public Path next(/*@NonEmpty Iterator this*/) {
                       if (i < getNameCount()) {
                           Path result = getName(i);
      diff --git a/src/java.base/share/classes/java/util/AbstractList.java b/src/java.base/share/classes/java/util/AbstractList.java
      index cd389c4c4d9..01d5928725c 100644
      --- a/src/java.base/share/classes/java/util/AbstractList.java
      +++ b/src/java.base/share/classes/java/util/AbstractList.java
      @@ -39,7 +39,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -394,7 +393,6 @@ public boolean hasNext() {
                   return cursor != size();
               }
       
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty Itr this) {
                   checkForComodification();
                   try {
      @@ -880,7 +878,6 @@ public boolean hasNext() {
                           return nextIndex() < size;
                       }
       
      -                @SideEffectsOnly("this")
                       public E next(/*@NonEmpty ListIterator this*/) {
                           if (hasNext())
                               return i.next();
      @@ -893,7 +890,6 @@ public boolean hasPrevious() {
                           return previousIndex() >= 0;
                       }
       
      -                @SideEffectsOnly("this")
                       public E previous() {
                           if (hasPrevious())
                               return i.previous();
      diff --git a/src/java.base/share/classes/java/util/AbstractMap.java b/src/java.base/share/classes/java/util/AbstractMap.java
      index 806a5146c43..5c8db70bcf5 100644
      --- a/src/java.base/share/classes/java/util/AbstractMap.java
      +++ b/src/java.base/share/classes/java/util/AbstractMap.java
      @@ -37,7 +37,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -390,7 +389,6 @@ public boolean hasNext() {
                                   return i.hasNext();
                               }
       
      -                        @SideEffectsOnly("this")
                               public K next(/*@NonEmpty Iterator this*/) {
                                   return i.next().getKey();
                               }
      @@ -457,7 +455,6 @@ public boolean hasNext() {
                                   return i.hasNext();
                               }
       
      -                        @SideEffectsOnly("this")
                               public V next(/*@NonEmpty Iterator this*/) {
                                   return i.next().getValue();
                               }
      diff --git a/src/java.base/share/classes/java/util/ArrayDeque.java b/src/java.base/share/classes/java/util/ArrayDeque.java
      index f564841142a..fd4351a35ef 100644
      --- a/src/java.base/share/classes/java/util/ArrayDeque.java
      +++ b/src/java.base/share/classes/java/util/ArrayDeque.java
      @@ -50,7 +50,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.io.Serializable;
      @@ -724,7 +723,6 @@ public final boolean hasNext() {
                   return remaining > 0;
               }
       
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty DeqIterator this) {
                   if (remaining <= 0)
                       throw new NoSuchElementException();
      diff --git a/src/java.base/share/classes/java/util/ArrayList.java b/src/java.base/share/classes/java/util/ArrayList.java
      index c9046eb8eec..eab7ee3ccd5 100644
      --- a/src/java.base/share/classes/java/util/ArrayList.java
      +++ b/src/java.base/share/classes/java/util/ArrayList.java
      @@ -42,7 +42,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -503,7 +502,6 @@ public E getLast() {
            * @return the element previously at the specified position
            * @throws IndexOutOfBoundsException {@inheritDoc}
            */
      -    @SideEffectsOnly("this")
           public E set(@GuardSatisfied ArrayList this, @NonNegative int index, E element) {
               Objects.checkIndex(index, size);
               E oldValue = elementData(index);
      @@ -516,7 +514,6 @@ public E set(@GuardSatisfied ArrayList this, @NonNegative int index, E elemen
            * bytecode size under 35 (the -XX:MaxInlineSize default value),
            * which helps when add(E) is called in a C1-compiled loop.
            */
      -    @SideEffectsOnly("this")
           private void add(E e, Object[] elementData, int s) {
               if (s == elementData.length)
                   elementData = grow();
      @@ -530,7 +527,6 @@ private void add(E e, Object[] elementData, int s) {
            * @param e element to be appended to this list
            * @return {@code true} (as specified by {@link Collection#add})
            */
      -    @SideEffectsOnly("this")
           @EnsuresNonEmpty("this")
           public boolean add(@GuardSatisfied ArrayList this, E e) {
               modCount++;
      @@ -547,7 +543,6 @@ public boolean add(@GuardSatisfied ArrayList this, E e) {
            * @param element element to be inserted
            * @throws IndexOutOfBoundsException {@inheritDoc}
            */
      -    @SideEffectsOnly("this")
           public void add(@GuardSatisfied ArrayList this, @NonNegative int index, E element) {
               rangeCheckForAdd(index);
               modCount++;
      @@ -792,7 +787,6 @@ public void clear(@GuardSatisfied @Shrinkable ArrayList this) {
            * @return {@code true} if this list changed as a result of the call
            * @throws NullPointerException if the specified collection is null
            */
      -    @SideEffectsOnly("this")
           public boolean addAll(@GuardSatisfied ArrayList this, Collection c) {
               Object[] a = c.toArray();
               modCount++;
      @@ -823,7 +817,6 @@ public boolean addAll(@GuardSatisfied ArrayList this, Collection
            * @throws IndexOutOfBoundsException {@inheritDoc}
            * @throws NullPointerException if the specified collection is null
            */
      -    @SideEffectsOnly("this")
           public boolean addAll(@GuardSatisfied ArrayList this, @NonNegative int index, Collection c) {
               rangeCheckForAdd(index);
       
      @@ -1094,7 +1087,6 @@ public boolean hasNext() {
               }
       
               @SuppressWarnings("unchecked")
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty Itr this) {
                   checkForComodification();
                   int i = cursor;
      @@ -1432,7 +1424,6 @@ public boolean hasNext() {
                       }
       
                       @SuppressWarnings("unchecked")
      -                @SideEffectsOnly("this")
                       public E next(/*@NonEmpty ListIterator this*/) {
                           checkForComodification();
                           int i = cursor;
      diff --git a/src/java.base/share/classes/java/util/Arrays.java b/src/java.base/share/classes/java/util/Arrays.java
      index 0ac094cf623..60f65d6ed47 100644
      --- a/src/java.base/share/classes/java/util/Arrays.java
      +++ b/src/java.base/share/classes/java/util/Arrays.java
      @@ -44,7 +44,6 @@
       import org.checkerframework.common.value.qual.MinLen;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -4413,7 +4412,6 @@ public boolean hasNext() {
               }
       
               @Override
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty ArrayItr this) {
                   int i = cursor;
                   if (i >= a.length) {
      diff --git a/src/java.base/share/classes/java/util/Collections.java b/src/java.base/share/classes/java/util/Collections.java
      index cfa74abe078..1e5565cf647 100644
      --- a/src/java.base/share/classes/java/util/Collections.java
      +++ b/src/java.base/share/classes/java/util/Collections.java
      @@ -45,7 +45,6 @@
       import org.checkerframework.common.value.qual.StaticallyExecutable;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -1122,7 +1121,6 @@ static class UnmodifiableCollection implements Collection, Serializable {
                       @Pure
                       @EnsuresNonEmptyIf(result = true, expression = "this")
                       public boolean hasNext() {return i.hasNext();}
      -                @SideEffectsOnly("this")
                       public E next(/*@NonEmpty Iterator this*/)          {return i.next();}
                       public void remove() {
                           throw new UnsupportedOperationException();
      @@ -1586,11 +1584,9 @@ public ListIterator listIterator(final int index) {
                       @Pure
                       @EnsuresNonEmptyIf(result = true, expression = "this")
                       public boolean hasNext()     {return i.hasNext();}
      -                @SideEffectsOnly("this")
                       public E next(/*@NonEmpty ListIterator this*/)              {return i.next();}
                       @Pure
                       public boolean hasPrevious() {return i.hasPrevious();}
      -                @SideEffectsOnly("this")
                       public E previous()          {return i.previous();}
                       public int nextIndex()       {return i.nextIndex();}
                       public int previousIndex()   {return i.previousIndex();}
      @@ -1930,7 +1926,6 @@ public Iterator> iterator() {
                           public boolean hasNext() {
                               return i.hasNext();
                           }
      -                    @SideEffectsOnly("this")
                           public Map.Entry next(/*@NonEmpty Iterator> this*/) {
                               return new UnmodifiableEntry<>(i.next());
                           }
      @@ -3519,7 +3514,6 @@ public Iterator iterator() {
                       @Pure
                       @EnsuresNonEmptyIf(result = true, expression = "this")
                       public boolean hasNext() { return it.hasNext(); }
      -                @SideEffectsOnly("this")
                       public E next(/*@NonEmpty Iterator this*/)          { return it.next(); }
                       public void remove()     {        it.remove(); }
                       public void forEachRemaining(Consumer action) {
      @@ -3918,7 +3912,6 @@ public ListIterator listIterator(final int index) {
                       @Pure
                       @EnsuresNonEmptyIf(result = true, expression = "this")
                       public boolean hasNext()     { return i.hasNext(); }
      -                @SideEffectsOnly("this")
                       public E next(/*@NonEmpty ListIterator this*/)              { return i.next(); }
                       public boolean hasPrevious() { return i.hasPrevious(); }
                       public E previous()          { return i.previous(); }
      @@ -4242,7 +4235,6 @@ public Iterator> iterator() {
                           @Pure
                           @EnsuresNonEmptyIf(result = true, expression = "this")
                           public boolean hasNext() { return i.hasNext(); }
      -                    @SideEffectsOnly("this")
                           public void remove()     { i.remove(); }
       
                           public Map.Entry next(/*@NonEmpty Iterator> this*/) {
      @@ -4698,7 +4690,6 @@ private static class EmptyIterator implements Iterator {
               @Pure
               @EnsuresNonEmptyIf(result = true, expression = "this")
               public boolean hasNext() { return false; }
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty EmptyIterator this) { throw new NoSuchElementException(); }
               public void remove(@NonEmpty EmptyIterator this) { throw new IllegalStateException(); }
               @Override
      @@ -5241,7 +5232,6 @@ static  Iterator singletonIterator(final E e) {
                   public boolean hasNext() {
                       return hasNext;
                   }
      -            @SideEffectsOnly("this")
                   public E next(/*@NonEmpty Iterator this*/) {
                       if (hasNext) {
                           hasNext = false;
      diff --git a/src/java.base/share/classes/java/util/EnumMap.java b/src/java.base/share/classes/java/util/EnumMap.java
      index 1d170eda873..880386c3749 100644
      --- a/src/java.base/share/classes/java/util/EnumMap.java
      +++ b/src/java.base/share/classes/java/util/EnumMap.java
      @@ -39,7 +39,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      diff --git a/src/java.base/share/classes/java/util/Enumeration.java b/src/java.base/share/classes/java/util/Enumeration.java
      index 5a51f493177..6298b0a0e85 100644
      --- a/src/java.base/share/classes/java/util/Enumeration.java
      +++ b/src/java.base/share/classes/java/util/Enumeration.java
      @@ -29,7 +29,6 @@
       import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf;
       import org.checkerframework.checker.nonempty.qual.NonEmpty;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       /**
      @@ -133,7 +132,6 @@ default Iterator asIterator() {
                   @Override public boolean hasNext() {
                       return hasMoreElements();
                   }
      -            @SideEffectsOnly("this")
                   @Override public E next(/*@NonEmpty Iterator this*/) {
                       return nextElement();
                   }
      diff --git a/src/java.base/share/classes/java/util/HashMap.java b/src/java.base/share/classes/java/util/HashMap.java
      index 23bcf9e7b96..d259da5c4d8 100644
      --- a/src/java.base/share/classes/java/util/HashMap.java
      +++ b/src/java.base/share/classes/java/util/HashMap.java
      @@ -39,7 +39,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -1649,7 +1648,6 @@ public final boolean hasNext() {
                   return next != null;
               }
       
      -        @SideEffectsOnly("this")
               final Node nextNode(@NonEmpty HashIterator this) {
                   Node[] t;
                   Node e = next;
      diff --git a/src/java.base/share/classes/java/util/HashSet.java b/src/java.base/share/classes/java/util/HashSet.java
      index 8cb8c1c1180..d54e501f294 100644
      --- a/src/java.base/share/classes/java/util/HashSet.java
      +++ b/src/java.base/share/classes/java/util/HashSet.java
      @@ -37,7 +37,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.io.InvalidObjectException;
      @@ -247,7 +246,6 @@ public boolean contains(@GuardSatisfied HashSet this, @GuardSatisfied @Nullab
            * @return {@code true} if this set did not already contain the specified
            * element
            */
      -    @SideEffectsOnly("this")
           @EnsuresNonEmpty("this")
           public boolean add(@GuardSatisfied HashSet this, E e) {
               return map.put(e, PRESENT)==null;
      @@ -265,7 +263,6 @@ public boolean add(@GuardSatisfied HashSet this, E e) {
            * @param o object to be removed from this set, if present
            * @return {@code true} if the set contained the specified element
            */
      -    @SideEffectsOnly("this")
           public boolean remove(@GuardSatisfied HashSet this, @GuardSatisfied @Nullable @UnknownSignedness Object o) {
               return map.remove(o)==PRESENT;
           }
      @@ -274,7 +271,6 @@ public boolean remove(@GuardSatisfied HashSet this, @GuardSatisfied @Nullable
            * Removes all of the elements from this set.
            * The set will be empty after this call returns.
            */
      -    @SideEffectsOnly("this")
           public void clear(@GuardSatisfied HashSet this) {
               map.clear();
           }
      diff --git a/src/java.base/share/classes/java/util/Hashtable.java b/src/java.base/share/classes/java/util/Hashtable.java
      index ef82f08a25b..b6673e0533b 100644
      --- a/src/java.base/share/classes/java/util/Hashtable.java
      +++ b/src/java.base/share/classes/java/util/Hashtable.java
      @@ -39,7 +39,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -1548,7 +1547,6 @@ public boolean hasNext() {
                   return hasMoreElements();
               }
       
      -        @SideEffectsOnly("this")
               public T next(@NonEmpty Enumerator this) {
                   if (Hashtable.this.modCount != expectedModCount)
                       throw new ConcurrentModificationException();
      diff --git a/src/java.base/share/classes/java/util/IdentityHashMap.java b/src/java.base/share/classes/java/util/IdentityHashMap.java
      index 6b70ff06197..d35b58c2411 100644
      --- a/src/java.base/share/classes/java/util/IdentityHashMap.java
      +++ b/src/java.base/share/classes/java/util/IdentityHashMap.java
      @@ -37,7 +37,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -782,7 +781,6 @@ public boolean hasNext() {
                   return false;
               }
       
      -        @SideEffectsOnly("this")
               protected int nextIndex(@NonEmpty IdentityHashMapIterator this) {
                   if (modCount != expectedModCount)
                       throw new ConcurrentModificationException();
      diff --git a/src/java.base/share/classes/java/util/ImmutableCollections.java b/src/java.base/share/classes/java/util/ImmutableCollections.java
      index 271b25cce9f..348ab7e48fc 100644
      --- a/src/java.base/share/classes/java/util/ImmutableCollections.java
      +++ b/src/java.base/share/classes/java/util/ImmutableCollections.java
      @@ -34,7 +34,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.io.IOException;
       import java.io.InvalidObjectException;
      @@ -389,7 +388,6 @@ public boolean hasNext() {
                   return cursor != size;
               }
       
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty ListItr this) {
                   try {
                       int i = cursor;
      @@ -863,7 +861,6 @@ public boolean hasNext() {
                       }
       
                       @Override
      -                @SideEffectsOnly("this")
                       @SuppressWarnings("unchecked")
                       public E next(/*@NonEmpty Iterator this*/) {
                           if (idx == 1) {
      @@ -1001,7 +998,6 @@ public boolean hasNext() {
                   }
       
                   @Override
      -            @SideEffectsOnly("this")
                   public E next(@NonEmpty SetNIterator this) {
                       if (remaining > 0) {
                           E element;
      @@ -1323,7 +1319,6 @@ public boolean hasNext() {
                       return remaining > 0;
                   }
       
      -            @SideEffectsOnly("this")
                   private int nextIndex() {
                       int idx = this.idx;
                       if (REVERSE) {
      diff --git a/src/java.base/share/classes/java/util/Iterator.java b/src/java.base/share/classes/java/util/Iterator.java
      index fb353dbdc2e..6bff1b79443 100644
      --- a/src/java.base/share/classes/java/util/Iterator.java
      +++ b/src/java.base/share/classes/java/util/Iterator.java
      @@ -30,7 +30,6 @@
       import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf;
       import org.checkerframework.checker.nonempty.qual.NonEmpty;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       import org.checkerframework.framework.qual.Covariant;
      @@ -88,7 +87,6 @@ public interface Iterator {
            * @return the next element in the iteration
            * @throws NoSuchElementException if the iteration has no more elements
            */
      -    @SideEffectsOnly("this")
           E next(@GuardSatisfied @NonEmpty Iterator this);
       
           /**
      diff --git a/src/java.base/share/classes/java/util/JumboEnumSet.java b/src/java.base/share/classes/java/util/JumboEnumSet.java
      index 6005a4c5bd0..75ea15f8307 100644
      --- a/src/java.base/share/classes/java/util/JumboEnumSet.java
      +++ b/src/java.base/share/classes/java/util/JumboEnumSet.java
      @@ -37,7 +37,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import org.checkerframework.checker.index.qual.NonNegative;
       import org.checkerframework.dataflow.qual.Pure;
      @@ -152,7 +151,6 @@ public boolean hasNext() {
       
               @Override
               @SuppressWarnings("unchecked")
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty EnumSetIterator this) {
                   if (!hasNext())
                       throw new NoSuchElementException();
      diff --git a/src/java.base/share/classes/java/util/LinkedHashMap.java b/src/java.base/share/classes/java/util/LinkedHashMap.java
      index 1f58fb94550..3afc9a99e87 100644
      --- a/src/java.base/share/classes/java/util/LinkedHashMap.java
      +++ b/src/java.base/share/classes/java/util/LinkedHashMap.java
      @@ -36,7 +36,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.util.function.Consumer;
      @@ -1054,7 +1053,6 @@ public final boolean hasNext() {
                   return next != null;
               }
       
      -        @SideEffectsOnly("this")
               final LinkedHashMap.Entry nextNode(@NonEmpty LinkedHashIterator this) {
                   LinkedHashMap.Entry e = next;
                   if (modCount != expectedModCount)
      diff --git a/src/java.base/share/classes/java/util/LinkedList.java b/src/java.base/share/classes/java/util/LinkedList.java
      index b3ed1fb5e19..f079b134dab 100644
      --- a/src/java.base/share/classes/java/util/LinkedList.java
      +++ b/src/java.base/share/classes/java/util/LinkedList.java
      @@ -41,7 +41,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -931,7 +930,6 @@ public boolean hasNext() {
                   return nextIndex < size;
               }
       
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty ListItr this) {
                   checkForComodification();
                   if (!hasNext())
      @@ -1044,7 +1042,6 @@ private class DescendingIterator implements Iterator {
               public boolean hasNext() {
                   return itr.hasPrevious();
               }
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty DescendingIterator this) {
                   return itr.previous();
               }
      diff --git a/src/java.base/share/classes/java/util/List.java b/src/java.base/share/classes/java/util/List.java
      index f1b027ca7f5..2ffcdeea06a 100644
      --- a/src/java.base/share/classes/java/util/List.java
      +++ b/src/java.base/share/classes/java/util/List.java
      @@ -43,7 +43,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -298,7 +297,6 @@ public interface List extends SequencedCollection {
            *         prevents it from being added to this list
            */
           @ReleasesNoLocks
      -    @SideEffectsOnly("this")
           @EnsuresNonEmpty("this")
           boolean add(@GuardSatisfied List this, E e);
       
      @@ -323,7 +321,6 @@ public interface List extends SequencedCollection {
            * @throws UnsupportedOperationException if the {@code remove} operation
            *         is not supported by this list
            */
      -    @SideEffectsOnly("this")
           boolean remove(@GuardSatisfied @Shrinkable List this, @UnknownSignedness Object o);
       
       
      @@ -371,7 +368,6 @@ public interface List extends SequencedCollection {
            *         specified collection prevents it from being added to this list
            * @see #add(Object)
            */
      -    @SideEffectsOnly("this")
           @EnsuresNonEmptyIf(result = true, expression = "this")
           boolean addAll(@GuardSatisfied List this, Collection c);
       
      @@ -402,7 +398,6 @@ public interface List extends SequencedCollection {
            * @throws IndexOutOfBoundsException if the index is out of range
            *         ({@code index < 0 || index > size()})
            */
      -    @SideEffectsOnly("this")
           @EnsuresNonEmptyIf(result = true, expression = "this")
           boolean addAll(@GuardSatisfied List this, @IndexOrHigh({"this"}) int index, Collection c);
       
      @@ -658,7 +653,6 @@ default void sort(@Nullable Comparator c) {
            *         ({@code index < 0 || index > size()})
            */
           @ReleasesNoLocks
      -    @SideEffectsOnly("this")
           void add(@GuardSatisfied List this, @IndexOrHigh({"this"}) int index, E element);
       
           /**
      diff --git a/src/java.base/share/classes/java/util/ListIterator.java b/src/java.base/share/classes/java/util/ListIterator.java
      index b44e644f1d3..3330d98ce20 100644
      --- a/src/java.base/share/classes/java/util/ListIterator.java
      +++ b/src/java.base/share/classes/java/util/ListIterator.java
      @@ -31,7 +31,6 @@
       import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf;
       import org.checkerframework.checker.nonempty.qual.NonEmpty;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -96,7 +95,6 @@ public interface ListIterator extends Iterator {
            * @return the next element in the list
            * @throws NoSuchElementException if the iteration has no next element
            */
      -    @SideEffectsOnly("this")
           E next(@GuardSatisfied @NonEmpty ListIterator this);
       
           /**
      diff --git a/src/java.base/share/classes/java/util/PriorityQueue.java b/src/java.base/share/classes/java/util/PriorityQueue.java
      index 082ec2aaffb..9cd7735b994 100644
      --- a/src/java.base/share/classes/java/util/PriorityQueue.java
      +++ b/src/java.base/share/classes/java/util/PriorityQueue.java
      @@ -41,7 +41,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -546,7 +545,6 @@ public boolean hasNext() {
                       (forgetMeNot != null && !forgetMeNot.isEmpty());
               }
       
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty Itr this) {
                   if (expectedModCount != modCount)
                       throw new ConcurrentModificationException();
      diff --git a/src/java.base/share/classes/java/util/RegularEnumSet.java b/src/java.base/share/classes/java/util/RegularEnumSet.java
      index a898d1090df..1e1fc49ae02 100644
      --- a/src/java.base/share/classes/java/util/RegularEnumSet.java
      +++ b/src/java.base/share/classes/java/util/RegularEnumSet.java
      @@ -38,7 +38,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       /**
      @@ -116,7 +115,6 @@ public boolean hasNext() {
                   return unseen != 0;
               }
       
      -        @SideEffectsOnly("this")
               @SuppressWarnings("unchecked")
               public E next(@NonEmpty EnumSetIterator this) {
                   if (unseen == 0)
      diff --git a/src/java.base/share/classes/java/util/Scanner.java b/src/java.base/share/classes/java/util/Scanner.java
      index bf688f497b5..7e1f1b16fda 100644
      --- a/src/java.base/share/classes/java/util/Scanner.java
      +++ b/src/java.base/share/classes/java/util/Scanner.java
      @@ -39,7 +39,6 @@
       import org.checkerframework.common.value.qual.IntRange;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.io.*;
      @@ -1490,7 +1489,6 @@ public boolean hasNext(@GuardSatisfied Scanner this) {
            * @throws IllegalStateException if this scanner is closed
            * @see java.util.Iterator
            */
      -    @SideEffectsOnly("this")
           public String next(@GuardSatisfied @NonEmpty Scanner this) {
               ensureOpen();
               clearCaches();
      @@ -1553,7 +1551,6 @@ public boolean hasNext(@GuardSatisfied Scanner this, String pattern)  {
            * @throws NoSuchElementException if no such tokens are available
            * @throws IllegalStateException if this scanner is closed
            */
      -    @SideEffectsOnly("this")
           public String next(@GuardSatisfied @NonEmpty Scanner this, String pattern)  {
               return next(patternCache.forName(pattern));
           }
      @@ -1604,7 +1601,6 @@ public boolean hasNext(@GuardSatisfied Scanner this, Pattern pattern) {
            * @throws NoSuchElementException if no more tokens are available
            * @throws IllegalStateException if this scanner is closed
            */
      -    @SideEffectsOnly("this")
           public String next(@GuardSatisfied @NonEmpty Scanner this, Pattern pattern) {
               ensureOpen();
               if (pattern == null)
      @@ -1678,7 +1674,6 @@ public boolean hasNextLine() {
            * @throws NoSuchElementException if no line was found
            * @throws IllegalStateException if this scanner is closed
            */
      -    @SideEffectsOnly("this")
           public String nextLine(@GuardSatisfied @NonEmpty Scanner this) {
               modCount++;
               if (hasNextPattern == linePattern())
      @@ -1928,7 +1923,6 @@ public boolean hasNextBoolean(@GuardSatisfied Scanner this)  {
            * @throws NoSuchElementException if input is exhausted
            * @throws IllegalStateException if this scanner is closed
            */
      -    @SideEffectsOnly("this")
           public boolean nextBoolean(@GuardSatisfied @NonEmpty Scanner this)  {
               clearCaches();
               return Boolean.parseBoolean(next(boolPattern()));
      @@ -1995,7 +1989,6 @@ public boolean hasNextByte(@GuardSatisfied Scanner this, @Positive @IntRange(fro
            * @throws NoSuchElementException if input is exhausted
            * @throws IllegalStateException if this scanner is closed
            */
      -    @SideEffectsOnly("this")
           public @PolySigned byte nextByte(@GuardSatisfied @NonEmpty Scanner this) {
                return nextByte(defaultRadix);
           }
      @@ -2031,7 +2024,6 @@ public boolean hasNextByte(@GuardSatisfied Scanner this, @Positive @IntRange(fro
            * @throws IllegalStateException if this scanner is closed
            * @throws IllegalArgumentException if the radix is out of range
            */
      -    @SideEffectsOnly("this")
           public @PolySigned byte nextByte(@GuardSatisfied @NonEmpty Scanner this, @Positive @IntRange(from = 2, to = 36) int radix) {
               // Check cached result
               if ((typeCache != null) && (typeCache instanceof Byte)
      @@ -2115,7 +2107,6 @@ public boolean hasNextShort(@GuardSatisfied Scanner this, @Positive @IntRange(fr
            * @throws NoSuchElementException if input is exhausted
            * @throws IllegalStateException if this scanner is closed
            */
      -    @SideEffectsOnly("this")
           public @PolySigned short nextShort(@GuardSatisfied @NonEmpty Scanner this) {
               return nextShort(defaultRadix);
           }
      @@ -2151,7 +2142,6 @@ public boolean hasNextShort(@GuardSatisfied Scanner this, @Positive @IntRange(fr
            * @throws IllegalStateException if this scanner is closed
            * @throws IllegalArgumentException if the radix is out of range
            */
      -    @SideEffectsOnly("this")
           public @PolySigned short nextShort(@GuardSatisfied @NonEmpty Scanner this, @Positive @IntRange(from = 2, to = 36) int radix) {
               // Check cached result
               if ((typeCache != null) && (typeCache instanceof Short)
      @@ -2259,7 +2249,6 @@ private String processIntegerToken(String token) {
            * @throws NoSuchElementException if input is exhausted
            * @throws IllegalStateException if this scanner is closed
            */
      -    @SideEffectsOnly("this")
           public @PolySigned int nextInt(@GuardSatisfied @NonEmpty Scanner this) {
               return nextInt(defaultRadix);
           }
      @@ -2295,7 +2284,6 @@ private String processIntegerToken(String token) {
            * @throws IllegalStateException if this scanner is closed
            * @throws IllegalArgumentException if the radix is out of range
            */
      -    @SideEffectsOnly("this")
           public @PolySigned int nextInt(@GuardSatisfied @NonEmpty Scanner this, @Positive @IntRange(from = 2, to = 36) int radix) {
               // Check cached result
               if ((typeCache != null) && (typeCache instanceof Integer)
      @@ -2379,7 +2367,6 @@ public boolean hasNextLong(@GuardSatisfied Scanner this, @Positive @IntRange(fro
            * @throws NoSuchElementException if input is exhausted
            * @throws IllegalStateException if this scanner is closed
            */
      -    @SideEffectsOnly("this")
           public @PolySigned long nextLong(@GuardSatisfied @NonEmpty Scanner this) {
               return nextLong(defaultRadix);
           }
      @@ -2415,7 +2402,6 @@ public boolean hasNextLong(@GuardSatisfied Scanner this, @Positive @IntRange(fro
            * @throws IllegalStateException if this scanner is closed
            * @throws IllegalArgumentException if the radix is out of range
            */
      -    @SideEffectsOnly("this")
           public @PolySigned long nextLong(@GuardSatisfied @NonEmpty Scanner this, @Positive @IntRange(from = 2, to = 36) int radix) {
               // Check cached result
               if ((typeCache != null) && (typeCache instanceof Long)
      @@ -2541,7 +2527,6 @@ public boolean hasNextFloat(@GuardSatisfied Scanner this) {
            * @throws NoSuchElementException if input is exhausted
            * @throws IllegalStateException if this scanner is closed
            */
      -    @SideEffectsOnly("this")
           public float nextFloat(@GuardSatisfied @NonEmpty Scanner this) {
               // Check cached result
               if ((typeCache != null) && (typeCache instanceof Float)) {
      @@ -2610,7 +2595,6 @@ public boolean hasNextDouble(@GuardSatisfied Scanner this) {
            * @throws NoSuchElementException if the input is exhausted
            * @throws IllegalStateException if this scanner is closed
            */
      -    @SideEffectsOnly("this")
           public double nextDouble(@GuardSatisfied @NonEmpty Scanner this) {
               // Check cached result
               if ((typeCache != null) && (typeCache instanceof Double)) {
      @@ -2695,7 +2679,6 @@ public boolean hasNextBigInteger(@GuardSatisfied Scanner this, @IntRange(from =
            * @throws NoSuchElementException if the input is exhausted
            * @throws IllegalStateException if this scanner is closed
            */
      -    @SideEffectsOnly("this")
           public BigInteger nextBigInteger(@GuardSatisfied @NonEmpty Scanner this) {
               return nextBigInteger(defaultRadix);
           }
      @@ -2726,7 +2709,6 @@ public BigInteger nextBigInteger(@GuardSatisfied @NonEmpty Scanner this) {
            * @throws IllegalStateException if this scanner is closed
            * @throws IllegalArgumentException if the radix is out of range
            */
      -    @SideEffectsOnly("this")
           public BigInteger nextBigInteger(@GuardSatisfied @NonEmpty Scanner this, @IntRange(from = 2, to = 36) int radix) {
               // Check cached result
               if ((typeCache != null) && (typeCache instanceof BigInteger val)
      @@ -2793,7 +2775,6 @@ public boolean hasNextBigDecimal(@GuardSatisfied Scanner this) {
            * @throws NoSuchElementException if the input is exhausted
            * @throws IllegalStateException if this scanner is closed
            */
      -    @SideEffectsOnly("this")
           public BigDecimal nextBigDecimal(@GuardSatisfied @NonEmpty Scanner this) {
               // Check cached result
               if ((typeCache != null) && (typeCache instanceof BigDecimal val)) {
      diff --git a/src/java.base/share/classes/java/util/ServiceLoader.java b/src/java.base/share/classes/java/util/ServiceLoader.java
      index f8574ad10e6..fb2c7cf1077 100644
      --- a/src/java.base/share/classes/java/util/ServiceLoader.java
      +++ b/src/java.base/share/classes/java/util/ServiceLoader.java
      @@ -32,7 +32,6 @@
       import org.checkerframework.checker.nullness.qual.Nullable;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.io.BufferedReader;
      @@ -978,7 +977,6 @@ public boolean hasNext() {
               }
       
               @Override
      -        @SideEffectsOnly("this")
               public Provider next(@NonEmpty LayerLookupIterator this) {
                   if (!hasNext())
                       throw new NoSuchElementException();
      @@ -1299,7 +1297,6 @@ public boolean hasNext() {
       
               @SuppressWarnings("removal")
               @Override
      -        @SideEffectsOnly("this")
               public Provider next(@NonEmpty LazyClassPathLookupIterator this) {
                   if (acc == null) {
                       return nextService();
      @@ -1330,7 +1327,6 @@ public boolean hasNext() {
                           return (first.hasNext() || second.hasNext());
                       }
                       @Override
      -                @SideEffectsOnly("this")
                       public Provider next(/*@NonEmpty Iterator> this*/) {
                           if (first.hasNext()) {
                               return first.next();
      @@ -1419,7 +1415,6 @@ public boolean hasNext() {
                   }
       
                   @Override
      -            @SideEffectsOnly("this")
                   public S next(/*@NonEmpty Iterator this*/) {
                       checkReloadCount();
                       S next;
      diff --git a/src/java.base/share/classes/java/util/Spliterators.java b/src/java.base/share/classes/java/util/Spliterators.java
      index 63a5d699f44..945746a1d20 100644
      --- a/src/java.base/share/classes/java/util/Spliterators.java
      +++ b/src/java.base/share/classes/java/util/Spliterators.java
      @@ -28,7 +28,6 @@
       import org.checkerframework.checker.nonempty.qual.NonEmpty;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import java.util.function.Consumer;
       import java.util.function.DoubleConsumer;
       import java.util.function.IntConsumer;
      @@ -699,7 +698,6 @@ public boolean hasNext() {
                   }
       
                   @Override
      -            @SideEffectsOnly("this")
                   public T next(@NonEmpty Adapter this) {
                       if (!valueReady && !hasNext())
                           throw new NoSuchElementException();
      @@ -761,7 +759,6 @@ public boolean hasNext() {
                   }
       
                   @Override
      -            @SideEffectsOnly("this")
                   public int nextInt(@NonEmpty Adapter this) {
                       if (!valueReady && !hasNext())
                           throw new NoSuchElementException();
      @@ -819,7 +816,6 @@ public boolean hasNext() {
                   }
       
                   @Override
      -            @SideEffectsOnly("this")
                   public long nextLong(@NonEmpty Adapter this) {
                       if (!valueReady && !hasNext())
                           throw new NoSuchElementException();
      @@ -877,7 +873,6 @@ public boolean hasNext() {
                   }
       
                   @Override
      -            @SideEffectsOnly("this")
                   public double nextDouble(@NonEmpty Adapter this) {
                       if (!valueReady && !hasNext())
                           throw new NoSuchElementException();
      diff --git a/src/java.base/share/classes/java/util/TreeMap.java b/src/java.base/share/classes/java/util/TreeMap.java
      index 337676c1856..f153893f594 100644
      --- a/src/java.base/share/classes/java/util/TreeMap.java
      +++ b/src/java.base/share/classes/java/util/TreeMap.java
      @@ -39,7 +39,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -1568,7 +1567,6 @@ public final boolean hasNext() {
                   return next != null;
               }
       
      -        @SideEffectsOnly("this")
               final Entry nextEntry() {
                   Entry e = next;
                   if (e == null)
      @@ -1580,7 +1578,6 @@ final Entry nextEntry() {
                   return e;
               }
       
      -        @SideEffectsOnly("this")
               final Entry prevEntry() {
                   Entry e = next;
                   if (e == null)
      @@ -2118,7 +2115,6 @@ public final boolean hasNext() {
                       return next != null && next.key != fenceKey;
                   }
       
      -            @SideEffectsOnly("this")
                   final TreeMap.Entry nextEntry() {
                       TreeMap.Entry e = next;
                       if (e == null || e.key == fenceKey)
      @@ -2130,7 +2126,6 @@ final TreeMap.Entry nextEntry() {
                       return e;
                   }
       
      -            @SideEffectsOnly("this")
                   final TreeMap.Entry prevEntry() {
                       TreeMap.Entry e = next;
                       if (e == null || e.key == fenceKey)
      diff --git a/src/java.base/share/classes/java/util/Vector.java b/src/java.base/share/classes/java/util/Vector.java
      index 7a18de73779..f6a71faefe2 100644
      --- a/src/java.base/share/classes/java/util/Vector.java
      +++ b/src/java.base/share/classes/java/util/Vector.java
      @@ -40,7 +40,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -826,7 +825,6 @@ private void add(E e, Object[] elementData, int s) {
            * @return {@code true} (as specified by {@link Collection#add})
            * @since 1.2
            */
      -    @SideEffectsOnly("this")
           @EnsuresNonEmpty("this")
           public synchronized boolean add(@GuardSatisfied Vector this, E e) {
               modCount++;
      @@ -1289,7 +1287,6 @@ public boolean hasNext() {
                   return cursor != elementCount;
               }
       
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty Itr this) {
                   synchronized (Vector.this) {
                       checkForComodification();
      diff --git a/src/java.base/share/classes/java/util/WeakHashMap.java b/src/java.base/share/classes/java/util/WeakHashMap.java
      index 0bf358ec1f6..1a403a8a56c 100644
      --- a/src/java.base/share/classes/java/util/WeakHashMap.java
      +++ b/src/java.base/share/classes/java/util/WeakHashMap.java
      @@ -38,7 +38,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -839,7 +838,6 @@ public boolean hasNext() {
               }
       
               /** The common parts of next() across different types of iterators */
      -        @SideEffectsOnly("this")
               protected Entry nextEntry() {
                   if (modCount != expectedModCount)
                       throw new ConcurrentModificationException();
      diff --git a/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java
      index 86749b755fa..48b2260d51c 100644
      --- a/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java
      +++ b/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java
      @@ -48,7 +48,6 @@
       import org.checkerframework.checker.signedness.qual.PolySigned;
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.lang.ref.WeakReference;
      @@ -1233,7 +1232,6 @@ private void noNext() {
                   }
               }
       
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty Itr this) {
                   final E e = nextItem;
                   if (e == null)
      diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java
      index e900a1df368..497c4280834 100644
      --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java
      +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java
      @@ -50,7 +50,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.io.ObjectStreamField;
      diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java
      index 0333416ff65..e5c0c9964c2 100644
      --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java
      +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java
      @@ -50,7 +50,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.lang.invoke.MethodHandles;
      @@ -1445,7 +1444,6 @@ public boolean hasNext() {
                   return nextItem != null;
               }
       
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty AbstractItr this) {
                   E item = nextItem;
                   if (item == null) throw new NoSuchElementException();
      diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java
      index 92876af30e2..5f8ccec2186 100644
      --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java
      +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java
      @@ -49,7 +49,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.lang.invoke.MethodHandles;
      @@ -802,7 +801,6 @@ public boolean hasNext() {
                   return nextItem != null;
               }
       
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty Itr this) {
                   final Node pred = nextNode;
                   if (pred == null) throw new NoSuchElementException();
      diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java
      index 9920296736f..42d47a97c72 100644
      --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java
      +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java
      @@ -47,7 +47,6 @@
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
       import org.checkerframework.framework.qual.AnnotatedFor;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.lang.invoke.MethodHandles;
       import java.lang.invoke.VarHandle;
      diff --git a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java
      index c84adbf1314..a88fce84ea7 100644
      --- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java
      +++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java
      @@ -49,7 +49,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.lang.invoke.VarHandle;
       import java.lang.reflect.Field;
      @@ -1207,7 +1206,6 @@ public boolean hasPrevious() {
               }
       
               @SuppressWarnings("unchecked")
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty COWIterator this) {
                   if (! hasNext())
                       throw new NoSuchElementException();
      @@ -1215,7 +1213,6 @@ public E next(@NonEmpty COWIterator this) {
               }
       
               @SuppressWarnings("unchecked")
      -        @SideEffectsOnly("this")
               public E previous() {
                   if (! hasPrevious())
                       throw new NoSuchElementException();
      @@ -1717,7 +1714,6 @@ public boolean hasNext() {
                   return nextIndex() < size;
               }
       
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty COWSubListIterator this) {
                   if (hasNext())
                       return it.next();
      diff --git a/src/java.base/share/classes/java/util/concurrent/DelayQueue.java b/src/java.base/share/classes/java/util/concurrent/DelayQueue.java
      index fb27e12d8bf..493fa19b734 100644
      --- a/src/java.base/share/classes/java/util/concurrent/DelayQueue.java
      +++ b/src/java.base/share/classes/java/util/concurrent/DelayQueue.java
      @@ -45,7 +45,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import static java.util.concurrent.TimeUnit.NANOSECONDS;
       
      @@ -583,7 +582,6 @@ public boolean hasNext() {
               }
       
               @SuppressWarnings("unchecked")
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty Itr this) {
                   if (cursor >= array.length)
                       throw new NoSuchElementException();
      diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java
      index 2c5ecfbb033..c4479427497 100644
      --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java
      +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java
      @@ -48,7 +48,6 @@
       import org.checkerframework.checker.signedness.qual.PolySigned;
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.util.AbstractQueue;
      @@ -1109,7 +1108,6 @@ public boolean hasNext() {
                   return next != null;
               }
       
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty AbstractItr this) {
                   Node p;
                   if ((p = next) == null)
      diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java
      index dc52c8b1cf8..c260d22481a 100644
      --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java
      +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java
      @@ -47,7 +47,6 @@
       import org.checkerframework.checker.signedness.qual.PolySigned;
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.util.AbstractQueue;
      @@ -808,7 +807,6 @@ public boolean hasNext() {
                   return next != null;
               }
       
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty Itr this) {
                   Node p;
                   if ((p = next) == null)
      diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java b/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java
      index 17f2e7bda19..816a2961599 100644
      --- a/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java
      +++ b/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java
      @@ -49,7 +49,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.framework.qual.AnnotatedFor;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.lang.invoke.MethodHandles;
       import java.lang.invoke.VarHandle;
      @@ -925,7 +924,6 @@ public final boolean hasNext() {
                   return nextNode != null;
               }
       
      -        @SideEffectsOnly("this")
               public final E next(@NonEmpty Itr this) {
                   final Node p;
                   if ((p = nextNode) == null) throw new NoSuchElementException();
      diff --git a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java
      index 61d3922e3d4..93fa3b5eb85 100644
      --- a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java
      +++ b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java
      @@ -48,7 +48,6 @@
       import org.checkerframework.checker.signedness.qual.PolySigned;
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.lang.invoke.MethodHandles;
      @@ -881,7 +880,6 @@ public boolean hasNext() {
                   return cursor < array.length;
               }
       
      -        @SideEffectsOnly("this")
               public E next(@NonEmpty Itr this) {
                   if (cursor >= array.length)
                       throw new NoSuchElementException();
      diff --git a/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java b/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java
      index b40a6a0ed12..d1c9a0d7fe9 100644
      --- a/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java
      +++ b/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java
      @@ -43,7 +43,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.framework.qual.AnnotatedFor;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import static java.util.concurrent.TimeUnit.MILLISECONDS;
       import static java.util.concurrent.TimeUnit.NANOSECONDS;
      @@ -1353,7 +1352,6 @@ public boolean hasNext() {
                       return cursor < array.length;
                   }
       
      -            @SideEffectsOnly("this")
                   public Runnable next(@NonEmpty Itr this) {
                       if (cursor >= array.length)
                           throw new NoSuchElementException();
      diff --git a/src/java.base/share/classes/java/util/regex/Matcher.java b/src/java.base/share/classes/java/util/regex/Matcher.java
      index 3c515170c9d..408d2e014b2 100644
      --- a/src/java.base/share/classes/java/util/regex/Matcher.java
      +++ b/src/java.base/share/classes/java/util/regex/Matcher.java
      @@ -35,7 +35,6 @@
       import org.checkerframework.checker.nullness.qual.Nullable;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       
       import java.io.IOException;
      @@ -1355,7 +1354,6 @@ class MatchResultIterator implements Iterator {
                   int expectedCount = -1;
       
                   @Override
      -            @SideEffectsOnly("this")
                   public MatchResult next(@NonEmpty MatchResultIterator this) {
                       if (expectedCount >= 0 && expectedCount != modCount)
                           throw new ConcurrentModificationException();
      diff --git a/src/java.base/share/classes/java/util/regex/Pattern.java b/src/java.base/share/classes/java/util/regex/Pattern.java
      index fc1ccc07132..60ca73a9cd6 100644
      --- a/src/java.base/share/classes/java/util/regex/Pattern.java
      +++ b/src/java.base/share/classes/java/util/regex/Pattern.java
      @@ -35,7 +35,6 @@
       import org.checkerframework.common.value.qual.MinLen;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -6085,7 +6084,6 @@ class MatcherIterator implements Iterator {
                   // > 0 if there are N next empty elements
                   private int emptyElementCount;
       
      -            @SideEffectsOnly("this")
                   public String next(@NonEmpty MatcherIterator this) {
                       if (!hasNext())
                           throw new NoSuchElementException();
      diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java
      index 9a96de226d3..81a30a68e84 100644
      --- a/src/java.base/share/classes/java/util/zip/ZipFile.java
      +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java
      @@ -36,7 +36,6 @@
       import org.checkerframework.checker.nullness.qual.Nullable;
       import org.checkerframework.checker.signedness.qual.SignedPositive;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.checkerframework.framework.qual.AnnotatedFor;
       import org.checkerframework.framework.qual.CFComment;
       
      @@ -529,14 +528,12 @@ public boolean hasNext() {
               }
       
               @Override
      -        @SideEffectsOnly("this")
               public T nextElement(@NonEmpty ZipEntryIterator this) {
                   return next();
               }
       
               @Override
               @SuppressWarnings("unchecked")
      -        @SideEffectsOnly("this")
               public T next(@NonEmpty ZipEntryIterator this) {
                   synchronized (ZipFile.this) {
                       ensureOpen();
      diff --git a/src/java.base/share/classes/javax/security/auth/Subject.java b/src/java.base/share/classes/javax/security/auth/Subject.java
      index 54a8c778242..7be2073cb03 100644
      --- a/src/java.base/share/classes/javax/security/auth/Subject.java
      +++ b/src/java.base/share/classes/javax/security/auth/Subject.java
      @@ -34,7 +34,6 @@
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
       import org.checkerframework.dataflow.qual.SideEffectFree;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.io.IOException;
       import java.io.ObjectInputStream;
      @@ -1207,7 +1206,6 @@ public boolean hasNext() {
                           return i.hasNext();
                       }
       
      -                @SideEffectsOnly("this")
                       public E next(/*@NonEmpty Iterator this*/) {
                           if (which != Subject.PRIV_CREDENTIAL_SET) {
                               return i.next();
      diff --git a/src/java.base/share/classes/org/checkerframework/dataflow/qual/SideEffectsOnly.java b/src/java.base/share/classes/org/checkerframework/dataflow/qual/SideEffectsOnly.java
      deleted file mode 100644
      index ab6a7dd1718..00000000000
      --- a/src/java.base/share/classes/org/checkerframework/dataflow/qual/SideEffectsOnly.java
      +++ /dev/null
      @@ -1,29 +0,0 @@
      -package org.checkerframework.dataflow.qual;
      -
      -import java.lang.annotation.Documented;
      -import java.lang.annotation.ElementType;
      -import java.lang.annotation.Retention;
      -import java.lang.annotation.RetentionPolicy;
      -import java.lang.annotation.Target;
      -import org.checkerframework.framework.qual.JavaExpression;
      -
      -/**
      - * A method annotated with the declaration annotation {@code @SideEffectsOnly("A", "B")} changes the
      - * value of at most the expressions A and B. All other expressions have the same value before and
      - * after a call to the method.
      - *
      - * @checker_framework.manual #type-refinement-purity Specifying side effects
      - */
      -@Documented
      -@Retention(RetentionPolicy.RUNTIME)
      -@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
      -public @interface SideEffectsOnly {
      -  /**
      -   * An upper bound on the expressions that this method might change the value of.
      -   *
      -   * @return the Java expressions that the annotated method might side-effect
      -   * @checker_framework.manual #java-expressions-as-arguments Syntax of Java expressions
      -   */
      -  @JavaExpression
      -  public String[] value();
      -}
      diff --git a/src/java.base/share/classes/sun/net/www/HeaderParser.java b/src/java.base/share/classes/sun/net/www/HeaderParser.java
      index ec69c47f035..a41ffb02116 100644
      --- a/src/java.base/share/classes/sun/net/www/HeaderParser.java
      +++ b/src/java.base/share/classes/sun/net/www/HeaderParser.java
      @@ -26,7 +26,6 @@
       package sun.net.www;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.util.Iterator;
       import java.util.Locale;
      @@ -208,7 +207,6 @@ class ParserIterator implements Iterator {
               public boolean hasNext () {
                   return index next() {
                               return new Map.Entry() {
                                   String k = i.next();
      diff --git a/src/java.base/share/classes/sun/util/locale/StringTokenIterator.java b/src/java.base/share/classes/sun/util/locale/StringTokenIterator.java
      index 7d0ab209641..5a5edc2823f 100644
      --- a/src/java.base/share/classes/sun/util/locale/StringTokenIterator.java
      +++ b/src/java.base/share/classes/sun/util/locale/StringTokenIterator.java
      @@ -31,7 +31,6 @@
       package sun.util.locale;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       public class StringTokenIterator {
           private String text;
      @@ -74,7 +73,6 @@ public boolean isDone() {
               return done;
           }
       
      -    @SideEffectsOnly("this")
           public String next() {
               if (hasNext()) {
                   start = end + 1;
      diff --git a/src/java.base/share/classes/sun/util/resources/ParallelListResourceBundle.java b/src/java.base/share/classes/sun/util/resources/ParallelListResourceBundle.java
      index e372d57d222..1200d1ce217 100644
      --- a/src/java.base/share/classes/sun/util/resources/ParallelListResourceBundle.java
      +++ b/src/java.base/share/classes/sun/util/resources/ParallelListResourceBundle.java
      @@ -28,7 +28,6 @@
       import org.checkerframework.checker.lock.qual.GuardSatisfied;
       import org.checkerframework.checker.signedness.qual.UnknownSignedness;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.util.AbstractSet;
       import java.util.Collections;
      @@ -240,7 +239,6 @@ public boolean hasNext() {
                       }
       
                       @Override
      -                @SideEffectsOnly("this")
                       public String next() {
                           if (hasNext()) {
                               return itr.next();
      diff --git a/src/java.base/unix/classes/java/lang/ProcessEnvironment.java b/src/java.base/unix/classes/java/lang/ProcessEnvironment.java
      index c91fca356b5..c030f652db2 100644
      --- a/src/java.base/unix/classes/java/lang/ProcessEnvironment.java
      +++ b/src/java.base/unix/classes/java/lang/ProcessEnvironment.java
      @@ -55,7 +55,6 @@
       package java.lang;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.util.*;
       
      @@ -338,7 +337,6 @@ public Iterator> iterator() {
                       Iterator> i = s.iterator();
                       @Pure
                       public boolean hasNext() {return i.hasNext();}
      -                @SideEffectsOnly("this")
                       public Map.Entry next() {
                           return new StringEntry(i.next());
                       }
      @@ -385,7 +383,6 @@ public Iterator iterator() {
                       Iterator i = c.iterator();
                       @Pure
                       public boolean hasNext() {return i.hasNext();}
      -                @SideEffectsOnly("this")
                       public String next()     {return i.next().toString();}
                       public void remove()     {i.remove();}
                   };
      @@ -416,7 +413,6 @@ public Iterator iterator() {
                       Iterator i = s.iterator();
                       @Pure
                       public boolean hasNext() {return i.hasNext();}
      -                @SideEffectsOnly("this")
                       public String next()     {return i.next().toString();}
                       public void remove()     {       i.remove();}
                   };
      diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixDirectoryStream.java b/src/java.base/unix/classes/sun/nio/fs/UnixDirectoryStream.java
      index 4ef0d19fc3c..68ad84da8aa 100644
      --- a/src/java.base/unix/classes/sun/nio/fs/UnixDirectoryStream.java
      +++ b/src/java.base/unix/classes/sun/nio/fs/UnixDirectoryStream.java
      @@ -26,7 +26,6 @@
       package sun.nio.fs;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.nio.file.*;
       import java.util.Iterator;
      @@ -204,7 +203,6 @@ public synchronized boolean hasNext() {
               }
       
               @Override
      -        @SideEffectsOnly("this")
               public synchronized Path next() {
                   Path result;
                   if (nextEntry == null && !atEof) {
      diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java
      index 6ddc73690aa..a4192da3b8a 100644
      --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java
      +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java
      @@ -26,7 +26,6 @@
       package sun.nio.fs;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.nio.ByteBuffer;
       import java.nio.file.AtomicMoveNotSupportedException;
      @@ -259,7 +258,6 @@ public synchronized boolean hasNext() {
               }
       
               @Override
      -        @SideEffectsOnly("this")
               public synchronized FileStore next() {
                   if (next == null)
                       next = readNext();
      diff --git a/src/java.base/windows/classes/java/lang/ProcessEnvironment.java b/src/java.base/windows/classes/java/lang/ProcessEnvironment.java
      index 8f0feb7519a..aba74f57fcd 100644
      --- a/src/java.base/windows/classes/java/lang/ProcessEnvironment.java
      +++ b/src/java.base/windows/classes/java/lang/ProcessEnvironment.java
      @@ -64,7 +64,6 @@
       package java.lang;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.util.*;
       
      @@ -145,7 +144,6 @@ public Iterator> iterator() {
                       Iterator> i = s.iterator();
                       @Pure
                       public boolean hasNext() { return i.hasNext();}
      -                @SideEffectsOnly("this")
                       public Map.Entry next() {
                           return new CheckedEntry(i.next());
                       }
      diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsDirectoryStream.java b/src/java.base/windows/classes/sun/nio/fs/WindowsDirectoryStream.java
      index 0916f458799..bb9b70e136a 100644
      --- a/src/java.base/windows/classes/sun/nio/fs/WindowsDirectoryStream.java
      +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsDirectoryStream.java
      @@ -26,7 +26,6 @@
       package sun.nio.fs;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.nio.file.*;
       import java.nio.file.attribute.BasicFileAttributes;
      @@ -215,7 +214,6 @@ public synchronized boolean hasNext() {
               }
       
               @Override
      -        @SideEffectsOnly("this")
               public synchronized Path next() {
                   Path result = null;
                   if (nextEntry == null && !atEof) {
      diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystem.java b/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystem.java
      index faf07b454b9..1d3eb09a0b8 100644
      --- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystem.java
      +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystem.java
      @@ -26,7 +26,6 @@
       package sun.nio.fs;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.nio.file.*;
       import java.nio.file.attribute.*;
      @@ -170,7 +169,6 @@ public synchronized boolean hasNext() {
               }
       
               @Override
      -        @SideEffectsOnly("this")
               public synchronized FileStore next() {
                   if (next == null)
                       next = readNext();
      diff --git a/src/java.management/share/classes/sun/management/counter/perf/PerfInstrumentation.java b/src/java.management/share/classes/sun/management/counter/perf/PerfInstrumentation.java
      index 9091b6aa347..47ba3c62317 100644
      --- a/src/java.management/share/classes/sun/management/counter/perf/PerfInstrumentation.java
      +++ b/src/java.management/share/classes/sun/management/counter/perf/PerfInstrumentation.java
      @@ -26,7 +26,6 @@
       package sun.management.counter.perf;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       
       import sun.management.counter.*;
      @@ -85,7 +84,6 @@ boolean hasNext() {
               return (nextEntry < prologue.getUsed());
           }
       
      -    @SideEffectsOnly("this")
           Counter getNextCounter() {
               if (! hasNext()) {
                   return null;
      diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HeaderParser.java b/src/java.net.http/share/classes/jdk/internal/net/http/HeaderParser.java
      index 099f323266d..8559a5467b8 100644
      --- a/src/java.net.http/share/classes/jdk/internal/net/http/HeaderParser.java
      +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HeaderParser.java
      @@ -26,7 +26,6 @@
       package jdk.internal.net.http;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.util.Iterator;
       import java.util.Locale;
      @@ -208,7 +207,6 @@ public boolean hasNext () {
                   return index= nkeys) {
                       throw new NoSuchElementException();
      diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java b/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java
      index 2fc75039a23..728db54ce5c 100644
      --- a/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java
      +++ b/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java
      @@ -26,7 +26,6 @@
       package jdk.internal.net.http;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.io.FileInputStream;
       import java.io.FileNotFoundException;
      @@ -140,7 +139,6 @@ public boolean hasNext() {
                   }
       
                   @Override
      -            @SideEffectsOnly("this")
                   public ByteBuffer next() {
                       ByteBuffer buffer = buffers.poll();
                       while (buffer == null) {
      @@ -471,7 +469,6 @@ private boolean hasNext0() {
               }
       
               @Override
      -        @SideEffectsOnly("this")
               public ByteBuffer next() {
                   stateLock.lock();
                   try {
      diff --git a/src/java.sql/share/classes/java/sql/SQLException.java b/src/java.sql/share/classes/java/sql/SQLException.java
      index 1142b6c9f1e..f77ab4ffbd9 100644
      --- a/src/java.sql/share/classes/java/sql/SQLException.java
      +++ b/src/java.sql/share/classes/java/sql/SQLException.java
      @@ -27,7 +27,6 @@
       
       import org.checkerframework.checker.nullness.qual.Nullable;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.util.Iterator;
       import java.util.NoSuchElementException;
      @@ -332,7 +331,6 @@ public boolean hasNext() {
                      return false;
                  }
       
      -           @SideEffectsOnly("this")
                  public Throwable next() {
                      Throwable throwable = null;
                      if(firstException != null){
      diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java
      index 3bdae38d075..b5d20e04bc3 100644
      --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java
      +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java
      @@ -32,7 +32,6 @@
       import java.util.concurrent.atomic.AtomicBoolean;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.w3c.dom.Element;
       import org.w3c.dom.Node;
       
      @@ -302,7 +301,6 @@ public boolean hasNext() {
                   return it.hasNext();
               }
       
      -        @SideEffectsOnly("this")
               public KeyResolverSpi next() {
                   KeyResolverSpi resolver = it.next();
                   if (resolver == null) {
      diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/StorageResolver.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/StorageResolver.java
      index 18230035d56..15924ca239b 100644
      --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/StorageResolver.java
      +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/StorageResolver.java
      @@ -23,7 +23,6 @@
       package com.sun.org.apache.xml.internal.security.keys.storage;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.security.KeyStore;
       import java.security.cert.Certificate;
      @@ -151,7 +150,6 @@ public boolean hasNext() {
               }
       
               /** {@inheritDoc} */
      -        @SideEffectsOnly("this")
               public Certificate next() {
                   if (hasNext()) {
                       return currentResolver.next();
      diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/KeyStoreResolver.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/KeyStoreResolver.java
      index 98984652a7c..4f0b44d9dc5 100644
      --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/KeyStoreResolver.java
      +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/KeyStoreResolver.java
      @@ -23,7 +23,6 @@
       package com.sun.org.apache.xml.internal.security.keys.storage.implementations;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.security.KeyStore;
       import java.security.KeyStoreException;
      @@ -112,7 +111,6 @@ public boolean hasNext() {
               }
       
               /** {@inheritDoc} */
      -        @SideEffectsOnly("this")
               public Certificate next() {
                   if (hasNext()) {
                       return this.certs.get(this.i++);
      diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/SingleCertificateResolver.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/SingleCertificateResolver.java
      index e5cef7a887e..d2c727bbe36 100644
      --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/SingleCertificateResolver.java
      +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/SingleCertificateResolver.java
      @@ -23,7 +23,6 @@
       package com.sun.org.apache.xml.internal.security.keys.storage.implementations;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.security.cert.Certificate;
       import java.security.cert.X509Certificate;
      @@ -80,7 +79,6 @@ public boolean hasNext() {
               }
       
               /** {@inheritDoc} */
      -        @SideEffectsOnly("this")
               public Certificate next() {
                   if (this.alreadyReturned) {
                       throw new NoSuchElementException();
      diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Reference.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Reference.java
      index 211b5168238..dc4bbbaf960 100644
      --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Reference.java
      +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Reference.java
      @@ -53,7 +53,6 @@
       import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverContext;
       import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.w3c.dom.Attr;
       import org.w3c.dom.Document;
       import org.w3c.dom.Element;
      @@ -626,7 +625,6 @@ public boolean hasNext() {
                                   }
       
                                   @Override
      -                            @SideEffectsOnly("this")
                                   public Node next() {
                                       return sIterator.next();
                                   }
      diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/reference/ReferenceSubTreeData.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/reference/ReferenceSubTreeData.java
      index c4ccc6336db..9d5ed1baa47 100644
      --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/reference/ReferenceSubTreeData.java
      +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/reference/ReferenceSubTreeData.java
      @@ -31,7 +31,6 @@
       import java.util.ListIterator;
       import java.util.NoSuchElementException;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.w3c.dom.NamedNodeMap;
       import org.w3c.dom.Node;
       
      @@ -89,7 +88,6 @@ public boolean hasNext() {
                   return li.hasNext();
               }
       
      -        @SideEffectsOnly("this")
               public Node next() {
                   if (nodeSet == null) {
                       nodeSet = dereferenceSameDocumentURI(root);
      diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSubTreeData.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSubTreeData.java
      index 78a03652f44..b893445c75c 100644
      --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSubTreeData.java
      +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSubTreeData.java
      @@ -32,7 +32,6 @@
       import java.util.ListIterator;
       import java.util.NoSuchElementException;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.w3c.dom.NamedNodeMap;
       import org.w3c.dom.Node;
       
      @@ -90,7 +89,6 @@ public boolean hasNext() {
                   return li.hasNext();
               }
       
      -        @SideEffectsOnly("this")
               public Node next() {
                   if (nodeSet == null) {
                       nodeSet = dereferenceSameDocumentURI(root);
      diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java
      index b5495418e36..72857b35472 100644
      --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java
      +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java
      @@ -20,7 +20,6 @@
       package com.sun.org.apache.bcel.internal.generic;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.io.ByteArrayOutputStream;
       import java.io.DataOutputStream;
      diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamFilterImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamFilterImpl.java
      index 6e7b4359056..7a36189f1ab 100644
      --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamFilterImpl.java
      +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamFilterImpl.java
      @@ -26,7 +26,6 @@
       package com.sun.org.apache.xerces.internal.impl;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import javax.xml.stream.XMLStreamReader;
       import javax.xml.stream.StreamFilter;
      @@ -97,7 +96,6 @@ protected void setStreamFilter(StreamFilter sf){
            * @return
            * @throws XMLStreamException
            */
      -    @SideEffectsOnly("this")
           public int next() throws XMLStreamException {
               if (fStreamAdvancedByHasNext && fEventAccepted) {
                   fStreamAdvancedByHasNext = false;
      diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamReaderImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamReaderImpl.java
      index efd888ab9d7..3dea188ad9b 100644
      --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamReaderImpl.java
      +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamReaderImpl.java
      @@ -26,7 +26,6 @@
       package com.sun.org.apache.xerces.internal.impl;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import com.sun.org.apache.xerces.internal.util.NamespaceContextWrapper;
       import com.sun.org.apache.xerces.internal.util.NamespaceSupport;
      diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XSModelImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XSModelImpl.java
      index e328cd63ba0..afaafc6a7cd 100644
      --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XSModelImpl.java
      +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XSModelImpl.java
      @@ -21,7 +21,6 @@
       package com.sun.org.apache.xerces.internal.impl.xs;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import com.sun.org.apache.xerces.internal.impl.Constants;
       import com.sun.org.apache.xerces.internal.impl.xs.util.StringListImpl;
      @@ -819,7 +818,6 @@ public XSNamespaceItemListIterator(int index) {
               public boolean hasNext() {
                   return (index < fGrammarCount);
               }
      -        @SideEffectsOnly("this")
               public XSNamespaceItem next() {
                   if (index < fGrammarCount) {
                       return fGrammarList[index++];
      diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/util/XSNamedMapImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/util/XSNamedMapImpl.java
      index 4fc5b349dc0..29c51a220a2 100644
      --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/util/XSNamedMapImpl.java
      +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/util/XSNamedMapImpl.java
      @@ -21,7 +21,6 @@
       package com.sun.org.apache.xerces.internal.impl.xs.util;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import com.sun.org.apache.xerces.internal.util.SymbolHash;
       import com.sun.org.apache.xerces.internal.xs.XSNamedMap;
       import com.sun.org.apache.xerces.internal.xs.XSObject;
      @@ -242,7 +241,6 @@ public Iterator> iterator() {
                               public boolean hasNext() {
                                   return (index < length);
                               }
      -                        @SideEffectsOnly("this")
                               public Map.Entry next() {
                                   if (index < length) {
                                       return entries[index++];
      diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/util/XSObjectListImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/util/XSObjectListImpl.java
      index 1b618554f28..04f8751cfc0 100644
      --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/util/XSObjectListImpl.java
      +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/util/XSObjectListImpl.java
      @@ -21,7 +21,6 @@
       package com.sun.org.apache.xerces.internal.impl.xs.util;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import com.sun.org.apache.xerces.internal.xs.XSObject;
       import com.sun.org.apache.xerces.internal.xs.XSObjectList;
       import java.lang.reflect.Array;
      @@ -52,7 +51,6 @@ static class EmptyIterator implements ListIterator {
               public boolean hasNext() {
                   return false;
               }
      -        @SideEffectsOnly("this")
               public XSObject next() {
                   throw new NoSuchElementException();
               }
      @@ -238,7 +236,6 @@ public XSObjectListIterator(int index) {
               public boolean hasNext() {
                   return (index < fLength);
               }
      -        @SideEffectsOnly("this")
               public XSObject next() {
                   if (index < fLength) {
                       return fArray[index++];
      diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/NamespaceSupport.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/NamespaceSupport.java
      index 5ca84d15b1c..b6045f03eb7 100644
      --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/NamespaceSupport.java
      +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/NamespaceSupport.java
      @@ -21,7 +21,6 @@
       package com.sun.org.apache.xerces.internal.util;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
       import java.util.ArrayList;
       import java.util.Enumeration;
      @@ -380,7 +379,6 @@ public boolean hasNext() {
               /**
                * @see java.util.Enumeration#nextElement()
                */
      -        @SideEffectsOnly("this")
               public String next() {
                   if (counter< size){
                       return fPrefixes[counter++];
      diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLAttributesIteratorImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLAttributesIteratorImpl.java
      index 9d04ba7cc86..e33d7cd3b85 100644
      --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLAttributesIteratorImpl.java
      +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLAttributesIteratorImpl.java
      @@ -26,7 +26,6 @@
       package com.sun.org.apache.xerces.internal.util;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.util.Iterator;
       import java.util.NoSuchElementException;
      @@ -63,7 +62,6 @@ public boolean hasNext() {
               return fCurrent < getLength() ? true : false ;
           }//hasNext()
       
      -    @SideEffectsOnly("this")
           public XMLAttributesImpl.Attribute next() {
               if(hasNext()){
                   // should this be of type javax.xml.stream.Attribute ?
      diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathNodesImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathNodesImpl.java
      index d48abf0d23b..37bbf74b5be 100644
      --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathNodesImpl.java
      +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathNodesImpl.java
      @@ -30,7 +30,6 @@
       import javax.xml.xpath.XPathNodes;
       import javax.xml.xpath.XPathEvaluationResult.XPathResultType;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.w3c.dom.Node;
       import org.w3c.dom.NodeList;
       
      @@ -67,7 +66,6 @@ public boolean hasNext() {
                   return false;
               }
       
      -        @SideEffectsOnly("this")
               public E next() {
                   if (nodeList != null && nodeList.getLength() > 0) {
                       return elementType.cast(nodeList.item(currentIndex++));
      diff --git a/src/java.xml/share/classes/com/sun/xml/internal/stream/EventFilterSupport.java b/src/java.xml/share/classes/com/sun/xml/internal/stream/EventFilterSupport.java
      index c02d2ed2d1d..5b90d7fff0d 100644
      --- a/src/java.xml/share/classes/com/sun/xml/internal/stream/EventFilterSupport.java
      +++ b/src/java.xml/share/classes/com/sun/xml/internal/stream/EventFilterSupport.java
      @@ -26,7 +26,6 @@
       package com.sun.xml.internal.stream;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.util.NoSuchElementException;
       import javax.xml.stream.EventFilter;
      @@ -50,7 +49,6 @@ public EventFilterSupport(XMLEventReader eventReader, EventFilter eventFilter) {
               fEventFilter = eventFilter;
           }
       
      -    @SideEffectsOnly("this")
           public Object next(){
               try{
                   return nextEvent();
      diff --git a/src/java.xml/share/classes/com/sun/xml/internal/stream/XMLEventReaderImpl.java b/src/java.xml/share/classes/com/sun/xml/internal/stream/XMLEventReaderImpl.java
      index d73cf911a9b..67d88d7c098 100644
      --- a/src/java.xml/share/classes/com/sun/xml/internal/stream/XMLEventReaderImpl.java
      +++ b/src/java.xml/share/classes/com/sun/xml/internal/stream/XMLEventReaderImpl.java
      @@ -26,7 +26,6 @@
       package com.sun.xml.internal.stream;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import com.sun.xml.internal.stream.events.XMLEventAllocatorImpl;
       import java.util.NoSuchElementException;
      @@ -75,7 +74,6 @@ public boolean hasNext() {
           }
       
       
      -    @SideEffectsOnly("this")
           public XMLEvent nextEvent() throws XMLStreamException {
               //if application peeked return the peeked event
               if(fPeekedEvent != null){
      diff --git a/src/java.xml/share/classes/com/sun/xml/internal/stream/util/ReadOnlyIterator.java b/src/java.xml/share/classes/com/sun/xml/internal/stream/util/ReadOnlyIterator.java
      index aa1fc45aacf..dabe06ae9ab 100644
      --- a/src/java.xml/share/classes/com/sun/xml/internal/stream/util/ReadOnlyIterator.java
      +++ b/src/java.xml/share/classes/com/sun/xml/internal/stream/util/ReadOnlyIterator.java
      @@ -30,7 +30,6 @@
        */
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import java.util.Iterator;
       
      @@ -54,7 +53,6 @@ public boolean hasNext() {
           }
       
           @Override
      -    @SideEffectsOnly("this")
           public T next() {
               if(iterator  != null)
                   return iterator.next();
      diff --git a/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java b/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java
      index 29642e67dea..81c43c989d4 100644
      --- a/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java
      +++ b/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java
      @@ -45,7 +45,6 @@
       import javax.xml.parsers.SAXParser;
       import javax.xml.parsers.SAXParserFactory;
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       import org.xml.sax.SAXException;
       
       /**
      @@ -350,7 +349,6 @@ public boolean hasNext() {
                   }
       
                   @Override
      -            @SideEffectsOnly("this")
                   public Catalog next() {
                       if (nextCatalog != null || hasNext()) {
                           Catalog catalog = nextCatalog;
      diff --git a/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java b/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java
      index 3a951d9e3e4..f255d860246 100644
      --- a/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java
      +++ b/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java
      @@ -26,7 +26,6 @@
       package javax.xml.stream;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import javax.xml.stream.events.XMLEvent;
       
      @@ -54,7 +53,6 @@ public interface XMLEventReader extends Iterator {
          * @throws XMLStreamException if there is an error with the underlying XML.
          * @throws java.util.NoSuchElementException iteration has no more elements.
          */
      -  @SideEffectsOnly("this")
         public XMLEvent nextEvent() throws XMLStreamException;
       
         /**
      diff --git a/src/java.xml/share/classes/javax/xml/stream/XMLStreamReader.java b/src/java.xml/share/classes/javax/xml/stream/XMLStreamReader.java
      index c9282b654e4..0214657df59 100644
      --- a/src/java.xml/share/classes/javax/xml/stream/XMLStreamReader.java
      +++ b/src/java.xml/share/classes/javax/xml/stream/XMLStreamReader.java
      @@ -26,7 +26,6 @@
       package javax.xml.stream;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import javax.xml.namespace.NamespaceContext;
       import javax.xml.namespace.QName;
      @@ -301,7 +300,6 @@ public interface XMLStreamReader extends XMLStreamConstants {
          * START_ELEMENT or END_ELEMENT
          * @throws java.util.NoSuchElementException if this is called when hasNext() returns false
          */
      -  @SideEffectsOnly("this")
         public int nextTag() throws XMLStreamException;
       
         /**
      diff --git a/src/java.xml/share/classes/javax/xml/stream/util/EventReaderDelegate.java b/src/java.xml/share/classes/javax/xml/stream/util/EventReaderDelegate.java
      index f83aa47c7a2..3e3a2afe05d 100644
      --- a/src/java.xml/share/classes/javax/xml/stream/util/EventReaderDelegate.java
      +++ b/src/java.xml/share/classes/javax/xml/stream/util/EventReaderDelegate.java
      @@ -26,7 +26,6 @@
       package javax.xml.stream.util;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import javax.xml.stream.XMLEventReader;
       import javax.xml.stream.events.XMLEvent;
      @@ -86,7 +85,6 @@ public XMLEvent nextEvent()
           return reader.nextEvent();
         }
       
      -  @SideEffectsOnly("this")
         public Object next() {
           return reader.next();
         }
      diff --git a/src/java.xml/share/classes/javax/xml/stream/util/StreamReaderDelegate.java b/src/java.xml/share/classes/javax/xml/stream/util/StreamReaderDelegate.java
      index 0865afaf040..64e332d8988 100644
      --- a/src/java.xml/share/classes/javax/xml/stream/util/StreamReaderDelegate.java
      +++ b/src/java.xml/share/classes/javax/xml/stream/util/StreamReaderDelegate.java
      @@ -26,7 +26,6 @@
       package javax.xml.stream.util;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       import javax.xml.namespace.QName;
       import javax.xml.namespace.NamespaceContext;
      diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java
      index 32f67ad38ca..dd2d2ba47f0 100644
      --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java
      +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java
      @@ -26,7 +26,6 @@
       package sun.nio.cs.ext;
       
       import org.checkerframework.dataflow.qual.Pure;
      -import org.checkerframework.dataflow.qual.SideEffectsOnly;
       
       
       import java.lang.ref.SoftReference;
      @@ -179,7 +178,6 @@ public boolean hasNext() {
                           return i.hasNext();
                       }
       
      -                @SideEffectsOnly("this")
                       public Charset next() {
                           String csn = i.next();
                           synchronized (AbstractCharsetProvider.this) {
      
      From e634e1d3c9df54f1588dd10f22c19f88acedaf3c Mon Sep 17 00:00:00 2001
      From: Werner Dietl 
      Date: Fri, 2 Oct 2026 00:58:13 -0400
      Subject: [PATCH 79/82] Remove duplicate @Pure annotations in doclets Utils
      
      Resolving the merge of master kept both the @Pure that this branch has and the
      one that master has on three methods, separated by a comment, so javac rejects
      them ("Pure is not a repeatable annotation interface").
      
      Co-Authored-By: Claude Sonnet 5.5 
      ---
       .../jdk/javadoc/internal/doclets/toolkit/util/Utils.java        | 2 --
       1 file changed, 2 deletions(-)
      
      diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
      index 87aefacf3ad..f4779f306ba 100644
      --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
      +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
      @@ -228,14 +228,12 @@ public boolean isAnnotationInterface(Element e) {
               return e.getKind() == ANNOTATION_TYPE;
           }
       
      -    @Pure
           // Note that e.getKind().isClass() is not the same as e.getKind() == CLASS
           @Pure
           public boolean isClass(Element e) {
               return e.getKind().isClass();
           }
       
      -    @Pure
           // Note that e.getKind().isInterface() is not the same as e.getKind() == INTERFACE
           // See Also: isPlainInterface(Element)
           @Pure
      
      From 770cdc076e20016cff49f5418e67e41b4001267f Mon Sep 17 00:00:00 2001
      From: Werner Dietl 
      Date: Fri, 2 Oct 2026 00:58:32 -0400
      Subject: [PATCH 80/82] Remove the remaining duplicate @Pure in doclets Utils
      
      Co-Authored-By: Claude Sonnet 5.5 
      ---
       .../classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java | 1 -
       1 file changed, 1 deletion(-)
      
      diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
      index f4779f306ba..0d375cbbfd8 100644
      --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
      +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
      @@ -291,7 +291,6 @@ public boolean isFinal(Element e) {
               return e.getModifiers().contains(Modifier.FINAL);
           }
       
      -    @Pure
           /*
            * A contemporary JLS term for "package private" or "default access" is
            * "package access". For example: "a member is declared with package
      
      From 55df90407aaaf6a67cf15406590dd484977b4dd9 Mon Sep 17 00:00:00 2001
      From: Werner Dietl 
      Date: Fri, 2 Oct 2026 19:06:54 -0400
      Subject: [PATCH 81/82] Match CanonicalName.java to the Checker Framework
      
      The Checker Framework master formatted its Javadoc with google-java-format
      1.36.1, which removes two blank comment lines here; the JDK consistency check
      requires identical qualifier files.
      
      Co-Authored-By: Claude Sonnet 5.5 
      ---
       .../checkerframework/checker/signature/qual/CanonicalName.java  | 2 --
       1 file changed, 2 deletions(-)
      
      diff --git a/src/java.base/share/classes/org/checkerframework/checker/signature/qual/CanonicalName.java b/src/java.base/share/classes/org/checkerframework/checker/signature/qual/CanonicalName.java
      index 862398dfc86..7c35c7eb2a5 100644
      --- a/src/java.base/share/classes/org/checkerframework/checker/signature/qual/CanonicalName.java
      +++ b/src/java.base/share/classes/org/checkerframework/checker/signature/qual/CanonicalName.java
      @@ -17,7 +17,6 @@
        * 6.7 gives the following example:
        *
        * 
      - * * The difference between a fully qualified name and a canonical name can be seen in code such as: * *
      {@code
      @@ -28,7 +27,6 @@
        *
        * Both {@code p.O1.I} and {@code p.O2.I} are fully qualified names that denote the member class
        * {@code I}, but only {@code p.O1.I} is its canonical name.
      - *
        * 
      * * Given a character sequence that is a fully-qualified name, there is no way to know whether or not From 1192a4fcef54d31b0b3edf6d08eb01a342e7fcd7 Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Fri, 2 Oct 2026 19:37:03 -0400 Subject: [PATCH 82/82] Fix two merge defects that break the JDK build Files.java imported Nullable twice instead of CFComment, and Objects.requireNonNull had @ForceInline twice ("ForceInline is not a repeatable annotation interface"). Both came from resolving the merge of master. Co-Authored-By: Claude Sonnet 5.5 --- src/java.base/share/classes/java/nio/file/Files.java | 2 +- src/java.base/share/classes/java/util/Objects.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java index aea66063a86..34edc66924a 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -35,7 +35,7 @@ import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; -import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.CFComment; import java.io.BufferedReader; import java.io.BufferedWriter; diff --git a/src/java.base/share/classes/java/util/Objects.java b/src/java.base/share/classes/java/util/Objects.java index e2368cb31c2..9544c1cce49 100644 --- a/src/java.base/share/classes/java/util/Objects.java +++ b/src/java.base/share/classes/java/util/Objects.java @@ -279,7 +279,6 @@ public static int compare(@GuardSatisfied @Nullable @UnknownSignedness T a, * @throws NullPointerException if {@code obj} is {@code null} */ @EnsuresNonNull("#1") - @ForceInline @SideEffectFree @ForceInline public static @NonNull T requireNonNull(@GuardSatisfied @NonNull @UnknownSignedness T obj, @Nullable String message) {
      
        *   {@literal @}EnsuresPresent("optStr")
      diff --git a/src/java.base/share/classes/org/checkerframework/checker/optional/qual/OptionalBottom.java b/src/java.base/share/classes/org/checkerframework/checker/optional/qual/OptionalBottom.java
      deleted file mode 100644
      index 755f071ec45..00000000000
      --- a/src/java.base/share/classes/org/checkerframework/checker/optional/qual/OptionalBottom.java
      +++ /dev/null
      @@ -1,20 +0,0 @@
      -package org.checkerframework.checker.optional.qual;
      -
      -import java.lang.annotation.Documented;
      -import java.lang.annotation.ElementType;
      -import java.lang.annotation.Retention;
      -import java.lang.annotation.RetentionPolicy;
      -import java.lang.annotation.Target;
      -import org.checkerframework.framework.qual.SubtypeOf;
      -
      -/**
      - * The bottom type qualifier for the Optional Checker. The only value of this type is {@code null}.
      - * Programmers rarely write this annotation.
      - *
      - * @checker_framework.manual #optional-checker Optional Checker
      - */
      -@Documented
      -@Retention(RetentionPolicy.RUNTIME)
      -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
      -@SubtypeOf({Present.class})
      -public @interface OptionalBottom {}
      diff --git a/src/java.base/share/classes/org/checkerframework/checker/signature/qual/BinaryNameWithoutPackage.java b/src/java.base/share/classes/org/checkerframework/checker/signature/qual/BinaryNameWithoutPackage.java
      deleted file mode 100644
      index 7a28a75be7e..00000000000
      --- a/src/java.base/share/classes/org/checkerframework/checker/signature/qual/BinaryNameWithoutPackage.java
      +++ /dev/null
      @@ -1,28 +0,0 @@
      -package org.checkerframework.checker.signature.qual;
      -
      -import java.lang.annotation.Documented;
      -import java.lang.annotation.ElementType;
      -import java.lang.annotation.Retention;
      -import java.lang.annotation.RetentionPolicy;
      -import java.lang.annotation.Target;
      -import org.checkerframework.framework.qual.SubtypeOf;
      -
      -/**
      - * Represents a string that is a {@link BinaryName}, an {@link InternalForm}, and a {@link
      - * ClassGetName}. The string represents a class that is in the unnamed package (also known as the
      - * default package).
      - *
      - * 

      Examples: - * - *

      {@code
      - * MyClass
      - * MyClass$22
      - * }
      - * - * @checker_framework.manual #signature-checker Signature Checker - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf({BinaryName.class, InternalForm.class}) -public @interface BinaryNameWithoutPackage {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/signature/qual/Identifier.java b/src/java.base/share/classes/org/checkerframework/checker/signature/qual/Identifier.java index c08108a3876..b1c3533d343 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/signature/qual/Identifier.java +++ b/src/java.base/share/classes/org/checkerframework/checker/signature/qual/Identifier.java @@ -12,11 +12,7 @@ * * @checker_framework.manual #signature-checker Signature Checker */ -@SubtypeOf({ - DotSeparatedIdentifiers.class, - BinaryNameWithoutPackage.class, - IdentifierOrPrimitiveType.class -}) +@SubtypeOf({DotSeparatedIdentifiers.class, IdentifierOrPrimitiveType.class, InternalForm.class}) @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) diff --git a/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/EnsuresInitializedFields.java b/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/EnsuresInitializedFields.java index 11e768f2294..fbdaa4e887e 100644 --- a/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/EnsuresInitializedFields.java +++ b/src/java.base/share/classes/org/checkerframework/common/initializedfields/qual/EnsuresInitializedFields.java @@ -50,7 +50,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/common/value/qual/EnsuresMinLenIf.java b/src/java.base/share/classes/org/checkerframework/common/value/qual/EnsuresMinLenIf.java index 89c04613c33..976d7e1b15f 100644 --- a/src/java.base/share/classes/org/checkerframework/common/value/qual/EnsuresMinLenIf.java +++ b/src/java.base/share/classes/org/checkerframework/common/value/qual/EnsuresMinLenIf.java @@ -65,7 +65,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/dataflow/qual/AssertMethod.java b/src/java.base/share/classes/org/checkerframework/dataflow/qual/AssertMethod.java index 4dd0ee58614..6f8319e2c43 100644 --- a/src/java.base/share/classes/org/checkerframework/dataflow/qual/AssertMethod.java +++ b/src/java.base/share/classes/org/checkerframework/dataflow/qual/AssertMethod.java @@ -14,9 +14,9 @@ *

      The annotation enables flow-sensitive type refinement to be more precise. For example, if * {@code Assertions.assertTrue} is annotated as follows: * - *

      @AssertMethod(value = AssertionFailedError.class)
      + * 
      {@code @AssertMethod(value = AssertionFailedError.class)
        * public static void assertFalse(boolean condition);
      - * 
      + * }
      * * Then, in the code below, the Optional Checker can determine that {@code optional} has a value and * the call to {@code Optional#get} will not throw an exception. @@ -53,15 +53,15 @@ int parameter() default 1; /** - * Returns whether this method asserts that the boolean expression is false. + * Returns true if this method asserts that the boolean expression is false. * *

      For example, Junit's Assertions.assertFalse(...) * throws an exception if the first argument is false. So it is annotated as follows: * - *

      @AssertMethod(value = AssertionFailedError.class, isAssertFalse = true)
      +   * 
      {@code @AssertMethod(value = AssertionFailedError.class, isAssertFalse = true)
          * public static void assertFalse(boolean condition);
      -   * 
      + * }
      * * @return the value for {@link #parameter} on which the method throws an exception */ diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultQualifier.java b/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultQualifier.java index 7409d914144..ac5e165fb94 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultQualifier.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/DefaultQualifier.java @@ -34,7 +34,7 @@ * @checker_framework.manual #defaults Default qualifier for unannotated types */ @Documented -@Retention(RetentionPolicy.SOURCE) +@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.PACKAGE, ElementType.TYPE, @@ -82,7 +82,7 @@ }) public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifier.java b/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifier.java index 3c897376109..eea9751edb5 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifier.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifier.java @@ -63,7 +63,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifierIf.java b/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifierIf.java index e5e6734255d..e7637ba890b 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifierIf.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/EnsuresQualifierIf.java @@ -77,7 +77,7 @@ @InheritedAnnotation public static @interface List { /** - * Return the repeatable annotations. + * Returns the repeatable annotations. * * @return the repeatable annotations */ diff --git a/src/java.base/share/classes/org/checkerframework/framework/qual/HasQualifierParameter.java b/src/java.base/share/classes/org/checkerframework/framework/qual/HasQualifierParameter.java index 9cc75018286..e48dbe60cab 100644 --- a/src/java.base/share/classes/org/checkerframework/framework/qual/HasQualifierParameter.java +++ b/src/java.base/share/classes/org/checkerframework/framework/qual/HasQualifierParameter.java @@ -9,13 +9,15 @@ import java.lang.annotation.Target; /** - * This is a declaration annotation that applies to type declarations and packages. On a type, it - * means that the class conceptually takes a type qualifier parameter, though there is nowhere to - * write it because the class hard-codes a Java basetype rather than taking a type parameter. - * Writing {@code HasQualifierParameter} on a package is the same as writing it on each class in - * that package. + * This is a declaration annotation that applies to type declarations and packages. On a + * type, it means that the class conceptually takes a type qualifier parameter, though there + * is nowhere to write it because the class hard-codes a Java basetype rather than taking a type + * parameter. Writing {@code HasQualifierParameter} on a package is the same as writing it on + * each class in that package. * - *

      Writing {@code @HasQualifierParameter} on a type declaration has two effects. + *

      Written on a type declaration

      + * + *

      Writing {@code @HasQualifierParameter} on a type declaration has two effects. * *

        *
      1. Invariant subtyping is used for occurrences of the type: no two occurrences of the type @@ -55,7 +57,10 @@ * {@code @Untainted} MyStringBuffer *