From 31676cecd33b0c56540ea981f7e64f5e8f414ff6 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sat, 27 Jan 2024 13:29:37 -0800 Subject: [PATCH 01/32] Don't use `--filter=blob:none` with `git-clone-related` --- azure-pipelines.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c7d85a5905a..d20041c91b1 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -45,10 +45,11 @@ jobs: fi displayName: plume-scripts # This creates ../jdk17u . - # If the depth is too small, the merge will fail. + # 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 - /tmp/$USER/plume-scripts/git-clone-related typetools jdk17u ../jdk17u -q --filter=blob:none + /tmp/$USER/plume-scripts/git-clone-related typetools jdk17u ../jdk17u -q --depth 999 displayName: clone-related-jdk17u - bash: | set -ex From 8993cd451c49e01dbb62f97c1a1893bd91b53087 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sun, 28 Jan 2024 12:31:12 -0800 Subject: [PATCH 02/32] Get `git-clone-related` from git-scripts repository, not plume-scripts --- azure-pipelines.yml | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d20041c91b1..cd8bf97744d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -37,6 +37,13 @@ jobs: 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 --filter=blob:none -q https://github.com/plume-lib/git-scripts.git ; \ + fi + displayName: git-scripts - bash: | set -ex if [ -d /tmp/$USER/plume-scripts ]; \ @@ -49,7 +56,7 @@ jobs: # because that leads to "fatal: remote error: filter 'combine' not supported". - bash: | set -ex - /tmp/$USER/plume-scripts/git-clone-related typetools jdk17u ../jdk17u -q --depth 999 + /tmp/$USER/git-scripts/git-clone-related typetools jdk17u ../jdk17u -q --depth 999 displayName: clone-related-jdk17u - bash: | set -ex @@ -84,9 +91,9 @@ jobs: steps: - checkout: self fetchDepth: 25 - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --filter=blob:none -q https://github.com/plume-lib/plume-scripts.git - displayName: clone plume-scripts - - bash: /tmp/$USER/plume-scripts/git-clone-related typetools checker-framework + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --filter=blob:none -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, but running its component parts in sequence does not. # - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh) @@ -116,9 +123,9 @@ jobs: steps: - checkout: self fetchDepth: 25 - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --filter=blob:none -q https://github.com/plume-lib/plume-scripts.git - displayName: clone plume-scripts - - bash: /tmp/$USER/plume-scripts/git-clone-related typetools checker-framework + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --filter=blob:none -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 @@ -131,9 +138,9 @@ jobs: steps: - checkout: self fetchDepth: 25 - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --filter=blob:none -q https://github.com/plume-lib/plume-scripts.git - displayName: clone plume-scripts - - bash: /tmp/$USER/plume-scripts/git-clone-related typetools checker-framework + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --filter=blob:none -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 @@ -146,9 +153,9 @@ jobs: steps: - checkout: self fetchDepth: 25 - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --filter=blob:none -q https://github.com/plume-lib/plume-scripts.git - displayName: clone plume-scripts - - bash: /tmp/$USER/plume-scripts/git-clone-related typetools checker-framework + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --filter=blob:none -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 @@ -160,9 +167,9 @@ jobs: steps: - checkout: self fetchDepth: 25 - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --filter=blob:none -q https://github.com/plume-lib/plume-scripts.git - displayName: clone plume-scripts - - bash: /tmp/$USER/plume-scripts/git-clone-related typetools checker-framework + - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --filter=blob:none -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 e987898d59ea4b456a1b9b3911a3dc1b2bd21232 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 20 Feb 2024 13:57:24 -0800 Subject: [PATCH 03/32] `File.pathSeparator` is a regex (at least on Unix and Windows) --- src/java.base/share/classes/java/io/File.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/io/File.java b/src/java.base/share/classes/java/io/File.java index 4736017b525..ea9f7ccfbc4 100644 --- a/src/java.base/share/classes/java/io/File.java +++ b/src/java.base/share/classes/java/io/File.java @@ -30,6 +30,7 @@ import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.lock.qual.ReleasesNoLocks; import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.checker.regex.qual.Regex; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -257,7 +258,7 @@ int getPrefixLength() { * for convenience. This string contains a single character, namely * {@link #pathSeparatorChar}. */ - public static final @Interned String pathSeparator = "" + pathSeparatorChar; + public static final @Interned @Regex String pathSeparator = "" + pathSeparatorChar; /* -- Constructors -- */ From b0434240e48255333b81a3271aa229509ae8cc39 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sun, 10 Mar 2024 17:03:27 -0700 Subject: [PATCH 04/32] Purity for boolean methods in `Files.java` --- azure-pipelines.yml | 6 +++--- src/java.base/share/classes/java/nio/file/Files.java | 12 ++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index cd8bf97744d..e82cf6bd5e0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -84,7 +84,7 @@ jobs: # displayName: make run-test - job: test_cftests_all_jdk11 - timeoutInMinutes: 105 + timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' container: mdernst/cf-ubuntu-jdk11:latest @@ -116,7 +116,7 @@ jobs: # displayName: publish all.tgz - job: test_cftests_all_jdk17 - timeoutInMinutes: 105 + timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' container: mdernst/cf-ubuntu-jdk17:latest @@ -131,7 +131,7 @@ jobs: displayName: test-cftests-all.sh - job: test_cftests_all_jdk20 - timeoutInMinutes: 105 + timeoutInMinutes: 120 pool: vmImage: 'ubuntu-latest' container: mdernst/cf-ubuntu-jdk20:latest 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 5009d795c51..1392b090c48 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -28,6 +28,8 @@ import org.checkerframework.checker.interning.qual.UsesObjectEquals; import org.checkerframework.checker.mustcall.qual.MustCall; import org.checkerframework.checker.signedness.qual.PolySigned; +import org.checkerframework.dataflow.qual.Pure; +import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; import java.io.BufferedReader; @@ -1543,6 +1545,7 @@ public static FileStore getFileStore(Path path) throws IOException { * * @see java.nio.file.attribute.BasicFileAttributes#fileKey */ + @SideEffectFree public static boolean isSameFile(Path path, Path path2) throws IOException { return provider(path).isSameFile(path, path2); } @@ -1645,6 +1648,7 @@ public static long mismatch(Path path, Path path2) throws IOException { * installed, the {@link SecurityManager#checkRead(String) checkRead} * method is invoked to check read access to the file. */ + @SideEffectFree public static boolean isHidden(Path path) throws IOException { return provider(path).isHidden(path); } @@ -2278,6 +2282,7 @@ public static Path setOwner(Path path, UserPrincipal owner) * installed, its {@link SecurityManager#checkRead(String) checkRead} * method denies read access to the file. */ + @SideEffectFree public static boolean isSymbolicLink(Path path) { try { return readAttributes(path, @@ -2317,6 +2322,7 @@ public static boolean isSymbolicLink(Path path) { * installed, its {@link SecurityManager#checkRead(String) checkRead} * method denies read access to the file. */ + @SideEffectFree public static boolean isDirectory(Path path, LinkOption... options) { if (options.length == 0) { FileSystemProvider provider = provider(path); @@ -2360,6 +2366,7 @@ public static boolean isDirectory(Path path, LinkOption... options) { * installed, its {@link SecurityManager#checkRead(String) checkRead} * method denies read access to the file. */ + @SideEffectFree public static boolean isRegularFile(Path path, LinkOption... options) { if (options.length == 0) { FileSystemProvider provider = provider(path); @@ -2521,6 +2528,7 @@ private static boolean followLinks(LinkOption... options) { * * @see #notExists */ + @SideEffectFree public static boolean exists(Path path, LinkOption... options) { if (options.length == 0) { FileSystemProvider provider = provider(path); @@ -2576,6 +2584,7 @@ public static boolean exists(Path path, LinkOption... options) { * SecurityManager#checkRead(String)} is invoked to check * read access to the file. */ + @SideEffectFree public static boolean notExists(Path path, LinkOption... options) { try { if (followLinks(options)) { @@ -2634,6 +2643,7 @@ private static boolean isAccessible(Path path, AccessMode... modes) { * installed, the {@link SecurityManager#checkRead(String) checkRead} * is invoked to check read access to the file. */ + @SideEffectFree public static boolean isReadable(Path path) { return isAccessible(path, AccessMode.READ); } @@ -2665,6 +2675,7 @@ public static boolean isReadable(Path path) { * installed, the {@link SecurityManager#checkWrite(String) checkWrite} * is invoked to check write access to the file. */ + @SideEffectFree public static boolean isWritable(Path path) { return isAccessible(path, AccessMode.WRITE); } @@ -2700,6 +2711,7 @@ public static boolean isWritable(Path path) { * installed, the {@link SecurityManager#checkExec(String) * checkExec} is invoked to check execute access to the file. */ + @SideEffectFree public static boolean isExecutable(Path path) { return isAccessible(path, AccessMode.EXECUTE); } From 9d75554036aaf7738c354bfb763f675b26c667ed Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 12 Mar 2024 18:06:38 -0700 Subject: [PATCH 05/32] Add purity annotations on `max()` --- src/java.base/share/classes/java/lang/Math.java | 8 ++++++++ .../share/classes/java/lang/StrictMath.java | 17 +++++++++++++++++ .../share/classes/java/math/BigDecimal.java | 5 +++++ .../share/classes/java/math/BigInteger.java | 5 +++++ .../share/classes/java/util/Collections.java | 9 +++++++++ 5 files changed, 44 insertions(+) diff --git a/src/java.base/share/classes/java/lang/Math.java b/src/java.base/share/classes/java/lang/Math.java index 3e77e78169e..2dda336c3ca 100644 --- a/src/java.base/share/classes/java/lang/Math.java +++ b/src/java.base/share/classes/java/lang/Math.java @@ -29,6 +29,7 @@ import org.checkerframework.checker.index.qual.PolyLowerBound; import org.checkerframework.checker.index.qual.PolyUpperBound; import org.checkerframework.checker.interning.qual.UsesObjectEquals; +import org.checkerframework.common.value.qual.StaticallyExecutable; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.framework.qual.AnnotatedFor; @@ -1594,6 +1595,7 @@ public static double abs(double a) { * @return the larger of {@code a} and {@code b}. */ @Pure + @StaticallyExecutable @IntrinsicCandidate public static @PolyUpperBound int max(@PolyUpperBound int a, @PolyUpperBound int b) { return (a >= b) ? a : b; @@ -1610,6 +1612,7 @@ public static double abs(double a) { * @return the larger of {@code a} and {@code b}. */ @Pure + @StaticallyExecutable public static @PolyUpperBound long max(@PolyUpperBound long a, @PolyUpperBound long b) { return (a >= b) ? a : b; } @@ -1633,6 +1636,7 @@ public static double abs(double a) { * @return the larger of {@code a} and {@code b}. */ @Pure + @StaticallyExecutable @IntrinsicCandidate public static float max(float a, float b) { if (a != a) @@ -1661,6 +1665,7 @@ public static float max(float a, float b) { * @return the larger of {@code a} and {@code b}. */ @Pure + @StaticallyExecutable @IntrinsicCandidate public static double max(double a, double b) { if (a != a) @@ -1701,6 +1706,7 @@ public static double max(double a, double b) { * @return the smaller of {@code a} and {@code b}. */ @Pure + @StaticallyExecutable public static @PolyLowerBound long min(@PolyLowerBound long a, @PolyLowerBound long b) { return (a <= b) ? a : b; } @@ -1720,6 +1726,7 @@ public static double max(double a, double b) { * @return the smaller of {@code a} and {@code b}. */ @Pure + @StaticallyExecutable @IntrinsicCandidate public static float min(float a, float b) { if (a != a) @@ -1748,6 +1755,7 @@ public static float min(float a, float b) { * @return the smaller of {@code a} and {@code b}. */ @Pure + @StaticallyExecutable @IntrinsicCandidate public static double min(double a, double b) { if (a != a) diff --git a/src/java.base/share/classes/java/lang/StrictMath.java b/src/java.base/share/classes/java/lang/StrictMath.java index d58b873778d..6b4275cca61 100644 --- a/src/java.base/share/classes/java/lang/StrictMath.java +++ b/src/java.base/share/classes/java/lang/StrictMath.java @@ -26,6 +26,7 @@ package java.lang; import org.checkerframework.checker.interning.qual.UsesObjectEquals; +import org.checkerframework.common.value.qual.StaticallyExecutable; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.framework.qual.AnnotatedFor; @@ -1298,6 +1299,8 @@ public static double abs(double a) { * @param b another argument. * @return the larger of {@code a} and {@code b}. */ + @Pure + @StaticallyExecutable @IntrinsicCandidate public static int max(int a, int b) { return Math.max(a, b); @@ -1313,6 +1316,8 @@ public static int max(int a, int b) { * @param b another argument. * @return the larger of {@code a} and {@code b}. */ + @Pure + @StaticallyExecutable public static long max(long a, long b) { return Math.max(a, b); } @@ -1331,6 +1336,8 @@ public static long max(long a, long b) { * @param b another argument. * @return the larger of {@code a} and {@code b}. */ + @Pure + @StaticallyExecutable @IntrinsicCandidate public static float max(float a, float b) { return Math.max(a, b); @@ -1350,6 +1357,8 @@ public static float max(float a, float b) { * @param b another argument. * @return the larger of {@code a} and {@code b}. */ + @Pure + @StaticallyExecutable @IntrinsicCandidate public static double max(double a, double b) { return Math.max(a, b); @@ -1365,6 +1374,8 @@ public static double max(double a, double b) { * @param b another argument. * @return the smaller of {@code a} and {@code b}. */ + @Pure + @StaticallyExecutable @IntrinsicCandidate public static int min(int a, int b) { return Math.min(a, b); @@ -1380,6 +1391,8 @@ public static int min(int a, int b) { * @param b another argument. * @return the smaller of {@code a} and {@code b}. */ + @Pure + @StaticallyExecutable public static long min(long a, long b) { return Math.min(a, b); } @@ -1398,6 +1411,8 @@ public static long min(long a, long b) { * @param b another argument. * @return the smaller of {@code a} and {@code b.} */ + @Pure + @StaticallyExecutable @IntrinsicCandidate public static float min(float a, float b) { return Math.min(a, b); @@ -1417,6 +1432,8 @@ public static float min(float a, float b) { * @param b another argument. * @return the smaller of {@code a} and {@code b}. */ + @Pure + @StaticallyExecutable @IntrinsicCandidate public static double min(double a, double b) { return Math.min(a, b); diff --git a/src/java.base/share/classes/java/math/BigDecimal.java b/src/java.base/share/classes/java/math/BigDecimal.java index ed6e9f99f63..6a3f1e75fe2 100644 --- a/src/java.base/share/classes/java/math/BigDecimal.java +++ b/src/java.base/share/classes/java/math/BigDecimal.java @@ -33,6 +33,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.common.value.qual.PolyValue; +import org.checkerframework.common.value.qual.StaticallyExecutable; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -3241,6 +3242,8 @@ public boolean equals(@Nullable Object x) { * method, {@code this} is returned. * @see #compareTo(java.math.BigDecimal) */ + @Pure + @StaticallyExecutable public BigDecimal min(BigDecimal val) { return (compareTo(val) <= 0 ? this : val); } @@ -3255,6 +3258,8 @@ public BigDecimal min(BigDecimal val) { * method, {@code this} is returned. * @see #compareTo(java.math.BigDecimal) */ + @Pure + @StaticallyExecutable public BigDecimal max(BigDecimal val) { return (compareTo(val) >= 0 ? this : val); } diff --git a/src/java.base/share/classes/java/math/BigInteger.java b/src/java.base/share/classes/java/math/BigInteger.java index 0418d10d2c9..18501a12715 100644 --- a/src/java.base/share/classes/java/math/BigInteger.java +++ b/src/java.base/share/classes/java/math/BigInteger.java @@ -34,6 +34,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.common.value.qual.IntRange; import org.checkerframework.common.value.qual.PolyValue; +import org.checkerframework.common.value.qual.StaticallyExecutable; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -3919,6 +3920,8 @@ public boolean equals(@Nullable Object x) { * @return the BigInteger whose value is the lesser of this BigInteger and * {@code val}. If they are equal, either may be returned. */ + @Pure + @StaticallyExecutable public BigInteger min(BigInteger val) { return (compareTo(val) < 0 ? this : val); } @@ -3930,6 +3933,8 @@ public BigInteger min(BigInteger val) { * @return the BigInteger whose value is the greater of this and * {@code val}. If they are equal, either may be returned. */ + @Pure + @StaticallyExecutable public BigInteger max(BigInteger val) { return (compareTo(val) > 0 ? this : val); } diff --git a/src/java.base/share/classes/java/util/Collections.java b/src/java.base/share/classes/java/util/Collections.java index 8f4ac325bc3..583508a31b1 100644 --- a/src/java.base/share/classes/java/util/Collections.java +++ b/src/java.base/share/classes/java/util/Collections.java @@ -37,6 +37,7 @@ import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.common.value.qual.ArrayLen; import org.checkerframework.common.value.qual.MinLen; +import org.checkerframework.common.value.qual.StaticallyExecutable; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -614,6 +615,8 @@ public static void copy(List dest, List src) { * @throws NoSuchElementException if the collection is empty. * @see Comparable */ + @Pure + @StaticallyExecutable public static > T min(Collection coll) { Iterator i = coll.iterator(); T candidate = i.next(); @@ -650,6 +653,8 @@ public static > T min(Collection T min(Collection coll, @Nullable Comparator comp) { if (comp==null) return (T)min((Collection) coll); @@ -687,6 +692,8 @@ public static T min(Collection coll, @Nullable Comparator> T max(Collection coll) { Iterator i = coll.iterator(); T candidate = i.next(); @@ -723,6 +730,8 @@ public static > T max(Collection T max(Collection coll, @Nullable Comparator comp) { if (comp==null) return (T)max((Collection) coll); From 422cb09793f7ee6ab82e4ee0d04c48117143c25f Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 28 Mar 2024 10:10:23 -0700 Subject: [PATCH 06/32] Add purity annotations to `Pattern.java` --- .../share/classes/java/util/regex/Pattern.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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 faf08678657..7efb6f58a0a 100644 --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -1116,6 +1116,7 @@ public static Pattern compile(@Regex String regex, int flags) { * * @return The source of this pattern */ + @Pure public String pattern() { return pattern; } @@ -1128,7 +1129,7 @@ public String pattern() { * @return The string representation of this pattern * @since 1.5 */ - @SideEffectFree + @Pure public String toString(@GuardSatisfied Pattern this) { return pattern; } @@ -1158,6 +1159,7 @@ public String toString(@GuardSatisfied Pattern this) { * * @return The match flags specified when this pattern was compiled */ + @Pure public int flags() { return flags0; } @@ -1188,6 +1190,7 @@ public int flags() { * @throws PatternSyntaxException * If the expression's syntax is invalid */ + @Pure public static boolean matches(@Regex String regex, CharSequence input) { Pattern p = Pattern.compile(regex); Matcher m = p.matcher(input); @@ -1273,6 +1276,7 @@ public static boolean matches(@Regex String regex, CharSequence input) { * @return The array of strings computed by splitting the input * around matches of this pattern */ + @Pure public String @MinLen(1) [] split(CharSequence input, int limit) { int index = 0; boolean matchLimited = limit > 0; @@ -1349,6 +1353,7 @@ public static boolean matches(@Regex String regex, CharSequence input) { * @return The array of strings computed by splitting the input * around matches of this pattern */ + @Pure public String @MinLen(1) [] split(CharSequence input) { return split(input, 0); } @@ -5793,6 +5798,7 @@ static CharPredicate CIRangeU(int lower, int upper) { * @since 1.8 * @see Matcher#find */ + @SideEffectFree public Predicate asPredicate() { return s -> matcher(s).find(); } @@ -5813,6 +5819,7 @@ public Predicate asPredicate() { * @since 11 * @see Matcher#matches */ + @SideEffectFree public Predicate asMatchPredicate() { return s -> matcher(s).matches(); } @@ -5849,6 +5856,7 @@ public Predicate asMatchPredicate() { * @see #split(CharSequence) * @since 1.8 */ + @SideEffectFree public Stream splitAsStream(final CharSequence input) { class MatcherIterator implements Iterator { private Matcher matcher; From 0e0489db166218a88ce072f1b03a12617b54cfbf Mon Sep 17 00:00:00 2001 From: James Yoo <24359440+jyoo980@users.noreply.github.com> Date: Fri, 26 Apr 2024 14:18:22 -0700 Subject: [PATCH 07/32] Apply formatting to README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 68b57a77ac3..43fbe3894f1 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,7 @@ 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. +``` last_common_commit=d562d3fcbe22a0443037c5b447e1a41401275814 cd $t/libraries git clone -- git@github.com:openjdk/jdk.git jdk-fork-openjdk-commit-${last_common_commit} @@ -163,7 +164,7 @@ git reset --hard ${last_common_commit} cd $t/libraries/jdk-fork-${USER}-branch-jdk${VER} git pull ../jdk-fork-openjdk-commit-${last_common_commit} - +``` ## Design From d125cc279020ec135d0e8ba1a17840e927bc8c25 Mon Sep 17 00:00:00 2001 From: James Yoo <24359440+jyoo980@users.noreply.github.com> Date: Sat, 11 May 2024 09:36:29 -0700 Subject: [PATCH 08/32] Annotate lambda parameter of `Iterable.forEach` with`@NonLeaked` --- checker-qual.jar | Bin 263555 -> 263522 bytes .../share/classes/java/lang/Iterable.java | 5 +++-- src/java.base/share/classes/module-info.java | 2 +- .../checker/builder/qual/CalledMethods.java | 2 +- .../formatter/qual/ConversionCategory.java | 2 +- .../checker/lock/qual/PolyGuardedBy.java | 14 +++++++------- 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/checker-qual.jar b/checker-qual.jar index 6d2bde5380728fe45574ca13331854a4cb471319..f4cba1fba62110f05f5e55f9af33c009c2cb870b 100644 GIT binary patch delta 26843 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 F{0|T$Xfgl* delta 27107 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 { /** * Returns an iterator over elements of type {@code T}. @@ -72,7 +73,7 @@ public interface Iterable { * @throws NullPointerException if the specified action is null * @since 1.8 */ - default void forEach(Consumer action) { + default void forEach(@NonLeaked Consumer action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index 4b4cc309a0e..52de1aea18c 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.i18nformatter.qual; exports org.checkerframework.checker.i18n.qual; + exports org.checkerframework.checker.i18nformatter.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/builder/qual/CalledMethods.java b/src/java.base/share/classes/org/checkerframework/checker/builder/qual/CalledMethods.java index a6083b5b52c..8ae314c7fcd 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 @@ -19,7 +19,7 @@ @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) public @interface CalledMethods { /** - * The names of methods that have definetely been called. + * The names of methods that have definitely been called. * * @return the names of methods that have definetely been called */ 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 ae132f0ed5e..07c28dc621c 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 @@ -144,7 +144,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/lock/qual/PolyGuardedBy.java b/src/java.base/share/classes/org/checkerframework/checker/lock/qual/PolyGuardedBy.java index a0ff940d74c..10214047b82 100644 --- a/src/java.base/share/classes/org/checkerframework/checker/lock/qual/PolyGuardedBy.java +++ b/src/java.base/share/classes/org/checkerframework/checker/lock/qual/PolyGuardedBy.java @@ -3,13 +3,13 @@ package org.checkerframework.checker.lock.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; +// 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 GuardedBy type system. From fcaecfe9548b26ef22ba8d8fd1cfefba1a25c4f1 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sat, 11 May 2024 12:49:01 -0700 Subject: [PATCH 09/32] Annotate `Record.java` --- src/java.base/share/classes/java/lang/Record.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Record.java b/src/java.base/share/classes/java/lang/Record.java index 2f8bd60ac5b..b81674db188 100644 --- a/src/java.base/share/classes/java/lang/Record.java +++ b/src/java.base/share/classes/java/lang/Record.java @@ -24,6 +24,9 @@ */ package java.lang; +import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.signedness.qual.UnknownSignedness; + /** * This is the common base class of all Java language record classes. * @@ -139,7 +142,7 @@ protected Record() {} * argument; {@code false} otherwise. */ @Override - public abstract boolean equals(Object obj); + public abstract boolean equals(@GuardSatisfied Record this, @GuardSatisfied Object obj); /** * Returns a hash code value for the record. @@ -165,7 +168,7 @@ protected Record() {} * @return a hash code value for this record. */ @Override - public abstract int hashCode(); + public abstract int hashCode(@GuardSatisfied @UnknownSignedness Record this); /** * Returns a string representation of the record. @@ -196,5 +199,5 @@ protected Record() {} * @return a string representation of the object. */ @Override - public abstract String toString(); + public abstract String toString(@GuardSatisfied Record this); } From 3afbd0f0ee25c0c7147ed88224e06c973482ae3e Mon Sep 17 00:00:00 2001 From: James Yoo <24359440+jyoo980@users.noreply.github.com> Date: Mon, 13 May 2024 08:14:51 -0700 Subject: [PATCH 10/32] Annotate `Map.forEach` lambda parameter with `@NonLeaked` --- src/java.base/share/classes/java/util/Map.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/util/Map.java b/src/java.base/share/classes/java/util/Map.java index 17374ac5e70..1fe509c010b 100644 --- a/src/java.base/share/classes/java/util/Map.java +++ b/src/java.base/share/classes/java/util/Map.java @@ -35,6 +35,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; import org.checkerframework.checker.signedness.qual.UnknownSignedness; +import org.checkerframework.common.aliasing.qual.NonLeaked; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -175,7 +176,7 @@ * @since 1.2 */ @CFComment({"lock/nullness: Subclasses of this interface/class may opt to prohibit null elements"}) -@AnnotatedFor({"lock", "nullness", "index"}) +@AnnotatedFor({"lock", "nullness", "index", "aliasing"}) public interface Map { // Query Operations @@ -739,7 +740,7 @@ default V getOrDefault(@GuardSatisfied @UnknownSignedness Object key, V defaultV * removed during iteration * @since 1.8 */ - default void forEach(BiConsumer action) { + default void forEach(@NonLeaked BiConsumer action) { Objects.requireNonNull(action); for (Map.Entry entry : entrySet()) { K k; From 6b98ceb4c203c580effcc4564a601dc8e30c3d78 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 14 May 2024 08:40:02 -0700 Subject: [PATCH 11/32] Make StringJoiner constructors `@SideEffectFree` --- src/java.base/share/classes/java/util/StringJoiner.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/java.base/share/classes/java/util/StringJoiner.java b/src/java.base/share/classes/java/util/StringJoiner.java index d2faba30c26..d8a39194f95 100644 --- a/src/java.base/share/classes/java/util/StringJoiner.java +++ b/src/java.base/share/classes/java/util/StringJoiner.java @@ -25,6 +25,7 @@ package java.util; import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; import jdk.internal.access.JavaLangAccess; @@ -105,6 +106,7 @@ public final class StringJoiner { * element added to the {@code StringJoiner} value * @throws NullPointerException if {@code delimiter} is {@code null} */ + @SideEffectFree public StringJoiner(CharSequence delimiter) { this(delimiter, "", ""); } @@ -124,6 +126,7 @@ public StringJoiner(CharSequence delimiter) { * @throws NullPointerException if {@code prefix}, {@code delimiter}, or * {@code suffix} is {@code null} */ + @SideEffectFree public StringJoiner(CharSequence delimiter, CharSequence prefix, CharSequence suffix) { @@ -165,6 +168,7 @@ public StringJoiner setEmptyValue(CharSequence emptyValue) { * * @return the string representation of this {@code StringJoiner} */ + @SideEffectFree @Override public String toString() { final int size = this.size; From 196d23ceb3f22b437dda93c0ed771c291a2398b0 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 24 May 2024 14:14:42 -0700 Subject: [PATCH 12/32] Locking annotations on `StringJoiner` --- src/java.base/share/classes/java/util/StringJoiner.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/java.base/share/classes/java/util/StringJoiner.java b/src/java.base/share/classes/java/util/StringJoiner.java index d8a39194f95..a3a8ce98d7c 100644 --- a/src/java.base/share/classes/java/util/StringJoiner.java +++ b/src/java.base/share/classes/java/util/StringJoiner.java @@ -24,7 +24,9 @@ */ package java.util; +import org.checkerframework.checker.lock.qual.ReleasesNoLocks; import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -190,6 +192,7 @@ public String toString() { * @param newElement The element to add * @return a reference to this {@code StringJoiner} */ + @ReleasesNoLocks public StringJoiner add(@Nullable CharSequence newElement) { final String elt = String.valueOf(newElement); if (elts == null) { @@ -232,6 +235,7 @@ private int checkAddLength(int oldLen, int inc) { * @throws NullPointerException if the other {@code StringJoiner} is null * @return This {@code StringJoiner} */ + @ReleasesNoLocks public StringJoiner merge(StringJoiner other) { Objects.requireNonNull(other); if (other.size == 0) { @@ -260,6 +264,7 @@ private void compactElts() { * * @return the length of the current value of {@code StringJoiner} */ + @Pure public int length() { return (size == 0 && emptyValue != null) ? emptyValue.length() : len + prefix.length() + suffix.length(); From 535fc22a61c049688479a3ec7fdceecb68ca73fb Mon Sep 17 00:00:00 2001 From: James Yoo <24359440+jyoo980@users.noreply.github.com> Date: Thu, 6 Jun 2024 13:35:35 -0700 Subject: [PATCH 13/32] Annotate `Enum#name()` with `@Pure` --- src/java.base/share/classes/java/lang/Enum.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/java.base/share/classes/java/lang/Enum.java b/src/java.base/share/classes/java/lang/Enum.java index 3814d663147..3628f0f3bf3 100644 --- a/src/java.base/share/classes/java/lang/Enum.java +++ b/src/java.base/share/classes/java/lang/Enum.java @@ -108,6 +108,7 @@ public abstract class Enum> * * @return the name of this enum constant */ + @Pure public final @PolyValue String name(@GuardedByUnknown @UnknownInitialization(java.lang.Enum.class) @PolyValue Enum this) { return name; } From 864c229905c4710ed929da687db262980734ac3b Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 6 Jun 2024 20:02:39 -0700 Subject: [PATCH 14/32] Enable debugging --- azure-pipelines.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e82cf6bd5e0..3e53bde569a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,3 +1,6 @@ +variables: + system.debug: true + jobs: - job: build_jdk From 2491638a41689722d9629c23209964c18ebdcf5d Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 20 Jun 2024 09:01:35 -0700 Subject: [PATCH 15/32] Break up cftests job into multiple steps --- azure-pipelines.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 3e53bde569a..9aaf2fa7ddd 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -98,7 +98,7 @@ 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, but running its component parts in sequence does not. +# 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) @@ -130,8 +130,17 @@ 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 - job: test_cftests_all_jdk20 timeoutInMinutes: 120 From 43353a2c98eaf2068610efba3712e9bed35dff0f Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 20 Jun 2024 09:06:00 -0700 Subject: [PATCH 16/32] Remove trailing blank line --- README-rewritten-jdk-history | 1 - 1 file changed, 1 deletion(-) diff --git a/README-rewritten-jdk-history b/README-rewritten-jdk-history index 42f5c77655e..5760120dc50 100644 --- a/README-rewritten-jdk-history +++ b/README-rewritten-jdk-history @@ -62,4 +62,3 @@ At each URL: * Queue the project in hopes that will start automatic building for each commit. * If the above doesn't work, change the instructions to the below: * Delete and re-create the pipeline, because of apparent caching problems when checking out the projects. - From 3590dfb72c8d58270d4c3307722f85b59cf655e3 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 20 Jun 2024 11:46:12 -0700 Subject: [PATCH 17/32] Improve instructions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 43fbe3894f1..2e7271e5835 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ Replace the existing export lines present in exports. If no new packages were added, then there are likely going to be no changes to the `module-info.java` file. -Commit the changes, including the changed top-level `checker-qual.jar` file. +Commit the changes, including any new `.java` files in a `qual/` directory. ## The typetools/jdk17u repository From c5d66ef32d10bb1d1e60fce983110a3e779bfd33 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 20 Jun 2024 23:33:01 -0700 Subject: [PATCH 18/32] Fix reference to README.md file --- azure-pipelines.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 9aaf2fa7ddd..6738eb17db2 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -59,7 +59,7 @@ jobs: # because that leads to "fatal: remote error: filter 'combine' not supported". - bash: | set -ex - /tmp/$USER/git-scripts/git-clone-related typetools jdk17u ../jdk17u -q --depth 999 + /tmp/$USER/git-scripts/git-clone-related typetools jdk17u ../jdk17u --depth 999 displayName: clone-related-jdk17u - bash: | set -ex @@ -68,7 +68,9 @@ jobs: git config --global pull.ff true git config --global pull.rebase false eval `/tmp/$USER/plume-scripts/ci-info typetools` - cd ../jdk17u && git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH} || (git --version && git show && echo "Merge failed; see 'Pull request merge conflicts' at https://github.com/typetools/jdk/blob/master/README" && false) + echo "About to run: git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH}" + cd ../jdk17u && git status + 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 From 550b857da7547b07fa8df9e6c6460273a02cef53 Mon Sep 17 00:00:00 2001 From: James Yoo <24359440+jyoo980@users.noreply.github.com> Date: Tue, 25 Jun 2024 12:17:51 -0400 Subject: [PATCH 19/32] Non-Empty Checker --- checker-qual.jar | Bin 263522 -> 269031 bytes .../share/classes/java/io/BufferedReader.java | 5 +- .../share/classes/java/lang/CharSequence.java | 9 +- .../share/classes/java/lang/ClassLoader.java | 5 +- .../share/classes/java/lang/Iterable.java | 3 +- .../classes/java/lang/StackStreamFactory.java | 4 +- .../share/classes/java/lang/String.java | 3 + .../lang/invoke/AbstractConstantGroup.java | 8 +- .../classes/java/lang/invoke/LambdaForm.java | 2 + .../classes/java/net/NetworkInterface.java | 7 +- src/java.base/share/classes/java/net/URL.java | 5 +- .../classes/java/net/URLClassLoader.java | 5 +- .../classes/java/nio/charset/Charset.java | 6 +- .../java/nio/file/FileTreeIterator.java | 6 +- .../share/classes/java/nio/file/Files.java | 5 +- .../share/classes/java/nio/file/Path.java | 5 +- .../classes/java/security/AllPermission.java | 7 +- .../classes/java/security/Permissions.java | 6 +- .../classes/java/util/AbstractCollection.java | 6 +- .../share/classes/java/util/AbstractList.java | 10 +- .../share/classes/java/util/AbstractMap.java | 13 ++- .../classes/java/util/AbstractQueue.java | 7 +- .../share/classes/java/util/ArrayDeque.java | 32 +++--- .../share/classes/java/util/ArrayList.java | 16 ++- .../share/classes/java/util/Arrays.java | 9 +- .../share/classes/java/util/BitSet.java | 2 + .../share/classes/java/util/Collection.java | 11 +- .../share/classes/java/util/Collections.java | 91 ++++++++++++----- .../share/classes/java/util/Deque.java | 25 +++-- .../share/classes/java/util/Dictionary.java | 2 + .../share/classes/java/util/EnumMap.java | 12 ++- .../share/classes/java/util/Enumeration.java | 9 +- .../share/classes/java/util/Formatter.java | 2 + .../share/classes/java/util/HashMap.java | 18 +++- .../share/classes/java/util/HashSet.java | 11 +- .../share/classes/java/util/Hashtable.java | 15 ++- .../classes/java/util/IdentityHashMap.java | 15 ++- .../java/util/ImmutableCollections.java | 30 ++++-- .../share/classes/java/util/Iterator.java | 5 +- .../share/classes/java/util/JumboEnumSet.java | 9 +- .../classes/java/util/LinkedHashMap.java | 17 +++- .../share/classes/java/util/LinkedList.java | 28 +++-- .../share/classes/java/util/List.java | 35 ++++--- .../share/classes/java/util/ListIterator.java | 5 +- .../share/classes/java/util/Map.java | 40 +++++--- .../classes/java/util/PrimitiveIterator.java | 7 +- .../classes/java/util/PriorityQueue.java | 11 +- .../share/classes/java/util/Properties.java | 11 +- .../share/classes/java/util/Queue.java | 9 +- .../classes/java/util/RegularEnumSet.java | 9 +- .../share/classes/java/util/Scanner.java | 43 ++++---- .../classes/java/util/ServiceLoader.java | 17 +++- .../share/classes/java/util/Set.java | 32 +++--- .../share/classes/java/util/SortedMap.java | 5 +- .../share/classes/java/util/SortedSet.java | 5 +- .../share/classes/java/util/Spliterators.java | 14 ++- .../share/classes/java/util/Stack.java | 5 +- .../classes/java/util/StringTokenizer.java | 10 +- .../share/classes/java/util/Timer.java | 2 + .../share/classes/java/util/TreeMap.java | 39 ++++--- .../share/classes/java/util/TreeSet.java | 19 ++-- .../share/classes/java/util/Vector.java | 19 +++- .../share/classes/java/util/WeakHashMap.java | 16 ++- .../util/concurrent/ArrayBlockingQueue.java | 8 +- .../java/util/concurrent/BlockingDeque.java | 11 +- .../java/util/concurrent/BlockingQueue.java | 7 +- .../util/concurrent/ConcurrentHashMap.java | 23 ++++- .../concurrent/ConcurrentLinkedDeque.java | 25 +++-- .../concurrent/ConcurrentLinkedQueue.java | 9 +- .../concurrent/ConcurrentSkipListMap.java | 34 +++++-- .../concurrent/ConcurrentSkipListSet.java | 10 +- .../util/concurrent/CopyOnWriteArrayList.java | 15 ++- .../util/concurrent/CopyOnWriteArraySet.java | 6 ++ .../java/util/concurrent/DelayQueue.java | 7 +- .../java/util/concurrent/ForkJoinPool.java | 2 + .../util/concurrent/LinkedBlockingDeque.java | 22 ++-- .../util/concurrent/LinkedBlockingQueue.java | 6 +- .../util/concurrent/LinkedTransferQueue.java | 9 +- .../concurrent/PriorityBlockingQueue.java | 8 +- .../ScheduledThreadPoolExecutor.java | 9 +- .../util/concurrent/SynchronousQueue.java | 3 + .../classes/java/util/jar/Attributes.java | 2 + .../share/classes/java/util/jar/JarFile.java | 8 +- .../classes/java/util/jar/JarVerifier.java | 12 ++- .../classes/java/util/regex/IntHashSet.java | 2 + .../classes/java/util/regex/Matcher.java | 5 +- .../classes/java/util/regex/Pattern.java | 5 +- .../util/stream/AbstractSpinedBuffer.java | 2 + .../classes/java/util/stream/Stream.java | 36 ++++--- .../share/classes/java/util/zip/ZipFile.java | 8 +- .../javax/crypto/CryptoPermissions.java | 7 +- .../javax/crypto/CryptoPolicyParser.java | 3 + .../classes/javax/security/auth/Subject.java | 10 +- src/java.base/share/classes/module-info.java | 1 + .../nonempty/qual/EnsuresNonEmpty.java | 53 ++++++++++ .../nonempty/qual/EnsuresNonEmptyIf.java | 87 ++++++++++++++++ .../checker/nonempty/qual/NonEmpty.java | 20 ++++ .../checker/nonempty/qual/PolyNonEmpty.java | 20 ++++ .../nonempty/qual/RequiresNonEmpty.java | 96 ++++++++++++++++++ .../nonempty/qual/UnknownNonEmpty.java | 22 ++++ 100 files changed, 1146 insertions(+), 306 deletions(-) create mode 100644 src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmpty.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmptyIf.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/NonEmpty.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/PolyNonEmpty.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/RequiresNonEmpty.java create mode 100644 src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/UnknownNonEmpty.java diff --git a/checker-qual.jar b/checker-qual.jar index f4cba1fba62110f05f5e55f9af33c009c2cb870b..8ad8c5c769691239b4e80a51b3464199f7b2cc5f 100644 GIT binary patch delta 27255 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 delta 22059 zcmZu32UJwYmiJ~s>e8f&f`VO&iX9bVZ-6ZtThthP!){arV=stVWvtjxV-!VKT`P#a ziw&_M*c%9HP-FXd=FXPKe$GjDGPjqxQ{GIT?{|8%(8(dX15uT=u&}naI5H78VUGXa$CnaP|MkJ7{jM6XUh?+p^LpQcanIkxke7<>~#ehatjsbw!2(R`NP2NL>W!Y z=yEhXO?ISTzYup_WWIcgv($~gCVL~<(FB=F4orz%nWGv+Nfs76HDgEna4OyQwelF0 zlU*clF2$22=)zlChx-5%(LJQF$m4uEbl|NR=X#6#nzPvav-+m z&z2_=ayx#rrm}Bio-=W=a!^u&WJ8k&N<1^EpTER<)bu6vaF-1~AMFuMEG){|fXnaatBJVpe;`3RfQmF*C@sU*+TW#AY+W5E{e%jC`BN&CIP-B| z2Kt@1w6OT-L^Hi1=y_8lH=R?g^n#B8-JxYt43cylCN)AfZ{|o*=(3Elk^@2yO_4m2 zV*W@e6rrC6N*g&;^DrZbIwlbZM`B?d(U8;{_d^|-8?-}@B%(U4iib>H1z8@XqRt~^ ze@5j(Q&$idt?tk+?nLd)V<&k-^W|tZ_hCXCxg~EDG?s#Bcz4;cv>aW(NVzX6dbqbf z@6)5@XzVMVAZKBK+V+)I*mrq|oPvE1r^w^b@UV`uFG3?m$%nC()kAK9Db~3C-t=;i zHBD5S5S>5QLznow+!*nkyUO2@-;06rQ0$x0UOtL_72C?c@V;$@<3#RG7$z@8;HgQn zCyFS$$!hRm@Qy7pis(N;o`ZPqz2uG9`aVW3KoM3WH#r*%+8<}XMEwb@ziaZI1?WJ5zY(Kc89Bt7r_5nrxjE@E zW;KN*3ZhOAiLF`gJg6eO5r(5nY$<<12GRB9TG$E+mCIx6UWB|CTf2hgUf7!1P`-=f zR9mZFRt+dXDR#7CT^MKm?-6IJzDLx$1%9#^Fnz-09!O_bN3MjeD}nL@4C?U!y{QM9 z$(4|+Rrb9dvEZENHf;2B{dIvg(Da z=+j{hWZ7B5Jq`@KbYFg!wxAk0QPNjzweKbkK_%6Z(pd~X48ahZaf3L}mqntWeJYY7 zd7!N~oU0K5F4%2L^NU~_4f!GY(5*L#w=Vg;)B$V8n~zd2Y_%(vN>GmN52+o>Y4=r1 z=PhPhI1eCL(u#A}OkEUQ5wz|k!=&U-<2Fe4x|vB*ZRGKNmoyS{VtYG>xY~d>lICSg z!Mb&)r3gg%x>Z_)N#(UudV~UV?o0iV>{iy6zg&T=A(C}Sk^He@6=!U{@EZV*n#k>R zSsIT_?e|Kvkin7fV>(0w-b&7Z?!HK@=m#n}>0GW#?Gbt5Khk1sxgC`HV(VkF)Dv5G z4od^Eb?KbcOR`~$0_QRvZEfk28&X|ezqL|%1pk^PEx=aw3sM5M=G~CGV=MoR^a5L* z?n(2pHSM@076T7&N*}PVbB;6?TZb=7KV!=;L$6HC7Cr4Ut-htD(n7?Wc|g)&D?3}7 zg00=hq|w-Fb`)AXW+$D?PW=ErDNwOW#A0Tr`@T_f76sKkc3&7k (lqZo1H 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 diff --git a/src/java.base/share/classes/java/io/BufferedReader.java b/src/java.base/share/classes/java/io/BufferedReader.java index bc66c9c86e1..5f1969535cf 100644 --- a/src/java.base/share/classes/java/io/BufferedReader.java +++ b/src/java.base/share/classes/java/io/BufferedReader.java @@ -33,6 +33,8 @@ import org.checkerframework.checker.index.qual.Positive; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.mustcall.qual.MustCallAlias; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.Pure; @@ -578,6 +580,7 @@ public Stream lines(@GuardSatisfied BufferedReader this) { String nextLine = null; @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (nextLine != null) { return true; @@ -592,7 +595,7 @@ public boolean hasNext() { } @Override - public String next() { + public String next(/*@NonEmpty Iterator this*/) { if (nextLine != null || hasNext()) { String line = nextLine; nextLine = null; diff --git a/src/java.base/share/classes/java/lang/CharSequence.java b/src/java.base/share/classes/java/lang/CharSequence.java index 48c24668d25..23f65fd72d0 100644 --- a/src/java.base/share/classes/java/lang/CharSequence.java +++ b/src/java.base/share/classes/java/lang/CharSequence.java @@ -30,6 +30,8 @@ import org.checkerframework.checker.index.qual.LengthOf; import org.checkerframework.checker.index.qual.SameLen; 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; @@ -110,6 +112,7 @@ public interface CharSequence { * @since 15 */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") default boolean isEmpty() { return this.length() == 0; } @@ -164,11 +167,12 @@ public default IntStream chars() { class CharIterator implements PrimitiveIterator.OfInt { int cur = 0; + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cur < length(); } - public int nextInt() { + public int nextInt(@NonEmpty CharIterator this) { if (hasNext()) { return charAt(cur++); } else { @@ -238,11 +242,12 @@ public void forEachRemaining(IntConsumer block) { } } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cur < length(); } - public int nextInt() { + public int nextInt(@NonEmpty CodePointIterator this) { final int length = length(); if (cur >= length) { diff --git a/src/java.base/share/classes/java/lang/ClassLoader.java b/src/java.base/share/classes/java/lang/ClassLoader.java index 4016c12b82d..7b74133897c 100644 --- a/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/src/java.base/share/classes/java/lang/ClassLoader.java @@ -27,6 +27,8 @@ package java.lang; import org.checkerframework.checker.interning.qual.UsesObjectEquals; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.RequiresNonNull; @@ -2754,11 +2756,12 @@ private boolean next() { return false; } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasMoreElements() { return next(); } - public E nextElement() { + public E nextElement(@NonEmpty CompoundEnumeration this) { if (!next()) { throw new NoSuchElementException(); } diff --git a/src/java.base/share/classes/java/lang/Iterable.java b/src/java.base/share/classes/java/lang/Iterable.java index f1bff3ebaf8..89990f6f8f7 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.nonempty.qual.PolyNonEmpty; import org.checkerframework.common.aliasing.qual.NonLeaked; import org.checkerframework.framework.qual.AnnotatedFor; @@ -49,7 +50,7 @@ public interface Iterable { * * @return an Iterator. */ - Iterator iterator(); + @PolyNonEmpty Iterator iterator(@PolyNonEmpty Iterable this); /** * Performs the given action for each element of the {@code Iterable} diff --git a/src/java.base/share/classes/java/lang/StackStreamFactory.java b/src/java.base/share/classes/java/lang/StackStreamFactory.java index 328154dc04e..4b142e5dba7 100644 --- a/src/java.base/share/classes/java/lang/StackStreamFactory.java +++ b/src/java.base/share/classes/java/lang/StackStreamFactory.java @@ -24,6 +24,7 @@ */ package java.lang; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import jdk.internal.reflect.MethodAccessor; import jdk.internal.reflect.ConstructorAccessor; import java.lang.StackWalker.Option; @@ -377,7 +378,7 @@ private R beginStackWalk() { * Fetches stack frames. * * @params batchSize number of elements of the frame buffers for this batch - * @returns number of frames fetched in this batch + * @return number of frames fetched in this batch */ private int fetchStackFrames(int batchSize) { int startIndex = frameBuffer.startIndex(); @@ -864,6 +865,7 @@ final int curBatchFrameCount() { /* * Tests if this frame buffer is empty. All frames are fetched. */ + @EnsuresNonEmptyIf(result = false, expression = "this") final boolean isEmpty() { return origin >= fence || (origin == START_POS && fence == 0); } diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index a89320f0550..babbf173c80 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -39,6 +39,7 @@ import org.checkerframework.checker.interning.qual.Interned; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.lock.qual.NewObject; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.regex.qual.PolyRegex; @@ -1556,6 +1557,7 @@ private static byte[] encodeUTF8_UTF16(byte[] val, boolean doReplace) { @StaticallyExecutable @EnsuresMinLenIf(expression="this", result=false, targetValue=1) @Override + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return value.length == 0; } @@ -2990,6 +2992,7 @@ public boolean matches(@Regex String regex) { */ @Pure @StaticallyExecutable + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(CharSequence s) { return indexOf(s.toString()) >= 0; } 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 b7703d8ca52..3f452e59b8b 100644 --- a/src/java.base/share/classes/java/lang/invoke/AbstractConstantGroup.java +++ b/src/java.base/share/classes/java/lang/invoke/AbstractConstantGroup.java @@ -25,6 +25,9 @@ package java.lang.invoke; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; + import java.util.*; import jdk.internal.vm.annotation.Stable; @@ -91,12 +94,13 @@ private AsIterator(ConstantGroup self, int start, int end, } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return index < end; } @Override - public Object next() { + public Object next(@NonEmpty AsIterator this) { int i = bumpIndex(); if (resolving) return self.get(i); @@ -104,7 +108,7 @@ public Object next() { return self.get(i, ifNotPresent); } - private int bumpIndex() { + private int bumpIndex(@NonEmpty AsIterator this) { int i = index; if (i >= end) throw new NoSuchElementException(); index = i+1; diff --git a/src/java.base/share/classes/java/lang/invoke/LambdaForm.java b/src/java.base/share/classes/java/lang/invoke/LambdaForm.java index 7792bf03ea2..81f80adb26f 100644 --- a/src/java.base/share/classes/java/lang/invoke/LambdaForm.java +++ b/src/java.base/share/classes/java/lang/invoke/LambdaForm.java @@ -25,6 +25,7 @@ package java.lang.invoke; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -1030,6 +1031,7 @@ private boolean resultCheck(Object[] argumentValues, Object result) { return true; } + @EnsuresNonEmptyIf(result = false, expression = "this") private boolean isEmpty() { if (result < 0) return (names.length == arity); diff --git a/src/java.base/share/classes/java/net/NetworkInterface.java b/src/java.base/share/classes/java/net/NetworkInterface.java index be1b2a63f2e..8513fefbf43 100644 --- a/src/java.base/share/classes/java/net/NetworkInterface.java +++ b/src/java.base/share/classes/java/net/NetworkInterface.java @@ -25,6 +25,8 @@ package java.net; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -412,11 +414,11 @@ public static Stream networkInterfaces() } private static Enumeration enumerationFromArray(T[] a) { - return new Enumeration<>() { + return new Enumeration() { int i = 0; @Override - public T nextElement() { + public T nextElement(/*@NonEmpty Enumeration this*/) { if (i < a.length) { return a[i++]; } else { @@ -425,6 +427,7 @@ public T nextElement() { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasMoreElements() { return i < a.length; } diff --git a/src/java.base/share/classes/java/net/URL.java b/src/java.base/share/classes/java/net/URL.java index c0f25d9c301..d5579c74aca 100644 --- a/src/java.base/share/classes/java/net/URL.java +++ b/src/java.base/share/classes/java/net/URL.java @@ -25,6 +25,8 @@ package java.net; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.NonNull; @@ -1339,11 +1341,12 @@ private boolean getNext() { return true; } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return getNext(); } - public URLStreamHandlerProvider next() { + public URLStreamHandlerProvider next(/*@NonEmpty Iterator this*/) { if (!getNext()) throw new NoSuchElementException(); URLStreamHandlerProvider n = next; diff --git a/src/java.base/share/classes/java/net/URLClassLoader.java b/src/java.base/share/classes/java/net/URLClassLoader.java index a083d8966e9..db9dd2253c3 100644 --- a/src/java.base/share/classes/java/net/URLClassLoader.java +++ b/src/java.base/share/classes/java/net/URLClassLoader.java @@ -25,6 +25,8 @@ package java.net; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.framework.qual.AnnotatedFor; @@ -670,7 +672,7 @@ public URL run() { return url != null; } - public URL nextElement() { + public URL nextElement(/*@NonEmpty Enumeration this*/) { if (!next()) { throw new NoSuchElementException(); } @@ -679,6 +681,7 @@ public URL nextElement() { return u; } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasMoreElements() { return next(); } 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 1880d8d99c7..4c48e91c634 100644 --- a/src/java.base/share/classes/java/nio/charset/Charset.java +++ b/src/java.base/share/classes/java/nio/charset/Charset.java @@ -25,7 +25,10 @@ package java.nio.charset; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.dataflow.qual.Pure; + import jdk.internal.misc.VM; import sun.nio.cs.ThreadLocalCoders; import sun.security.action.GetPropertyAction; @@ -353,11 +356,12 @@ private boolean getNext() { return true; } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return getNext(); } - public CharsetProvider next() { + public CharsetProvider next(/*@NonEmpty Iterator this*/) { if (!getNext()) throw new NoSuchElementException(); CharsetProvider n = next; 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 c748e32571b..8035d7b29b8 100644 --- a/src/java.base/share/classes/java/nio/file/FileTreeIterator.java +++ b/src/java.base/share/classes/java/nio/file/FileTreeIterator.java @@ -25,6 +25,9 @@ package java.nio.file; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; + import java.io.Closeable; import java.io.IOException; import java.io.UncheckedIOException; @@ -97,6 +100,7 @@ private void fetchNextIfNeeded() { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (!walker.isOpen()) throw new IllegalStateException(); @@ -105,7 +109,7 @@ public boolean hasNext() { } @Override - public Event next() { + public Event next(@NonEmpty FileTreeIterator this) { if (!walker.isOpen()) throw new IllegalStateException(); fetchNextIfNeeded(); 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 1392b090c48..a7985256031 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -27,6 +27,8 @@ import org.checkerframework.checker.interning.qual.UsesObjectEquals; import org.checkerframework.checker.mustcall.qual.MustCall; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.signedness.qual.PolySigned; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; @@ -3814,6 +3816,7 @@ public static Path writeString(Path path, CharSequence csq, Charset cs, OpenOpti // Re-wrap DirectoryIteratorException to UncheckedIOException Iterator iterator = new Iterator<>() { @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { try { return delegate.hasNext(); @@ -3822,7 +3825,7 @@ public boolean hasNext() { } } @Override - public Path next() { + public Path next(/*@NonEmpty Iterator this*/) { try { return delegate.next(); } catch (DirectoryIteratorException e) { 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 705bd341b36..73b9a0b1351 100644 --- a/src/java.base/share/classes/java/nio/file/Path.java +++ b/src/java.base/share/classes/java/nio/file/Path.java @@ -25,6 +25,8 @@ package java.nio.file; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; @@ -950,12 +952,13 @@ default Iterator iterator() { private int i = 0; @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return (i < getNameCount()); } @Override - public Path next() { + public Path next(/*@NonEmpty Iterator this*/) { if (i < getNameCount()) { Path result = getName(i); i++; diff --git a/src/java.base/share/classes/java/security/AllPermission.java b/src/java.base/share/classes/java/security/AllPermission.java index f6b3dc00d5f..4001722df21 100644 --- a/src/java.base/share/classes/java/security/AllPermission.java +++ b/src/java.base/share/classes/java/security/AllPermission.java @@ -25,6 +25,8 @@ package java.security; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -229,11 +231,12 @@ public Enumeration elements() { return new Enumeration<>() { private boolean hasMore = all_allowed; - public boolean hasMoreElements() { + @EnsuresNonEmptyIf(result = true, expression = "this") + public boolean hasMoreElements(/**/) { return hasMore; } - public Permission nextElement() { + public Permission nextElement(/*@NonEmpty Enumeration this*/) { hasMore = false; return SecurityConstants.ALL_PERMISSION; } diff --git a/src/java.base/share/classes/java/security/Permissions.java b/src/java.base/share/classes/java/security/Permissions.java index 1c489b6b266..a4014934df5 100644 --- a/src/java.base/share/classes/java/security/Permissions.java +++ b/src/java.base/share/classes/java/security/Permissions.java @@ -25,6 +25,9 @@ package java.security; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; + import java.io.InvalidObjectException; import java.io.IOException; import java.io.ObjectInputStream; @@ -442,6 +445,7 @@ final class PermissionsEnumerator implements Enumeration { } // No need to synchronize; caller should sync on object as required + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasMoreElements() { // if we enter with permissionimpl null, we know // there are no more left. @@ -462,7 +466,7 @@ public boolean hasMoreElements() { } // No need to synchronize; caller should sync on object as required - public Permission nextElement() { + public Permission nextElement(@NonEmpty PermissionsEnumerator this) { // hasMoreElements will update permset to the next permset // with something in it... diff --git a/src/java.base/share/classes/java/util/AbstractCollection.java b/src/java.base/share/classes/java/util/AbstractCollection.java index bdd7d8b6fea..b9f991dab08 100644 --- a/src/java.base/share/classes/java/util/AbstractCollection.java +++ b/src/java.base/share/classes/java/util/AbstractCollection.java @@ -27,6 +27,8 @@ import org.checkerframework.checker.index.qual.NonNegative; 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.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; import org.checkerframework.checker.signedness.qual.PolySigned; @@ -90,7 +92,7 @@ protected AbstractCollection() { * @return an iterator over the elements contained in this collection */ @SideEffectFree - public abstract Iterator iterator(); + public abstract @PolyNonEmpty Iterator iterator(@PolyNonEmpty AbstractCollection this); @Pure public abstract @NonNegative int size(@GuardSatisfied AbstractCollection this); @@ -102,6 +104,7 @@ protected AbstractCollection() { * This implementation returns {@code size() == 0}. */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty(@GuardSatisfied AbstractCollection this) { return size() == 0; } @@ -117,6 +120,7 @@ public boolean isEmpty(@GuardSatisfied AbstractCollection this) { * @throws NullPointerException {@inheritDoc} */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied AbstractCollection this, @GuardSatisfied @UnknownSignedness Object o) { Iterator it = iterator(); if (o==null) { diff --git a/src/java.base/share/classes/java/util/AbstractList.java b/src/java.base/share/classes/java/util/AbstractList.java index e6aaeded561..e1f077c6c80 100644 --- a/src/java.base/share/classes/java/util/AbstractList.java +++ b/src/java.base/share/classes/java/util/AbstractList.java @@ -29,6 +29,9 @@ import org.checkerframework.checker.index.qual.IndexFor; import org.checkerframework.checker.index.qual.IndexOrHigh; 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.nullness.qual.Nullable; import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; @@ -121,6 +124,7 @@ protected AbstractList() { * @throws IllegalArgumentException if some property of this element * prevents it from being added to this list */ + @EnsuresNonEmpty("this") public boolean add(@GuardSatisfied AbstractList this, E e) { add(size(), e); return true; @@ -378,11 +382,12 @@ private class Itr implements Iterator { */ int expectedModCount = modCount; + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor != size(); } - public E next() { + public E next(@NonEmpty Itr this) { checkForComodification(); try { int i = cursor; @@ -861,11 +866,12 @@ public ListIterator listIterator(int index) { private final ListIterator i = root.listIterator(offset + index); + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return nextIndex() < size; } - public E next() { + public E next(/*@NonEmpty ListIterator this*/) { if (hasNext()) return i.next(); else diff --git a/src/java.base/share/classes/java/util/AbstractMap.java b/src/java.base/share/classes/java/util/AbstractMap.java index 2b9ee3fb1cc..0325dccb016 100644 --- a/src/java.base/share/classes/java/util/AbstractMap.java +++ b/src/java.base/share/classes/java/util/AbstractMap.java @@ -28,6 +28,8 @@ import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.lock.qual.ReleasesNoLocks; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresKeyFor; import org.checkerframework.checker.nullness.qual.EnsuresKeyForIf; import org.checkerframework.checker.nullness.qual.KeyFor; @@ -110,6 +112,7 @@ protected AbstractMap() { * This implementation returns {@code size() == 0}. */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty(@GuardSatisfied AbstractMap this) { return size() == 0; } @@ -377,11 +380,12 @@ public Iterator iterator() { return new Iterator() { private Iterator> i = entrySet().iterator(); + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return i.hasNext(); } - public K next() { + public K next(/*@NonEmpty Iterator this*/) { return i.next().getKey(); } @@ -397,6 +401,7 @@ public int size() { } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return AbstractMap.this.isEmpty(); } @@ -405,6 +410,7 @@ public void clear() { AbstractMap.this.clear(); } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object k) { return AbstractMap.this.containsKey(k); } @@ -439,11 +445,12 @@ public Iterator iterator() { return new Iterator() { private Iterator> i = entrySet().iterator(); + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return i.hasNext(); } - public V next() { + public V next(/*@NonEmpty Iterator this*/) { return i.next().getValue(); } @@ -459,6 +466,7 @@ public int size() { } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return AbstractMap.this.isEmpty(); } @@ -467,6 +475,7 @@ public void clear() { AbstractMap.this.clear(); } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object v) { return AbstractMap.this.containsValue(v); } diff --git a/src/java.base/share/classes/java/util/AbstractQueue.java b/src/java.base/share/classes/java/util/AbstractQueue.java index 083136086ac..b5cdfce96f9 100644 --- a/src/java.base/share/classes/java/util/AbstractQueue.java +++ b/src/java.base/share/classes/java/util/AbstractQueue.java @@ -36,6 +36,8 @@ package java.util; import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.framework.qual.AnnotatedFor; /** @@ -95,6 +97,7 @@ protected AbstractQueue() { * @throws IllegalArgumentException if some property of this element * prevents it from being added to this queue */ + @EnsuresNonEmpty("this") public boolean add(@GuardSatisfied AbstractQueue this, E e) { if (offer(e)) return true; @@ -113,7 +116,7 @@ public boolean add(@GuardSatisfied AbstractQueue this, E e) { * @return the head of this queue * @throws NoSuchElementException if this queue is empty */ - public E remove(@GuardSatisfied AbstractQueue this) { + public E remove(@GuardSatisfied @NonEmpty AbstractQueue this) { E x = poll(); if (x != null) return x; @@ -132,7 +135,7 @@ public E remove(@GuardSatisfied AbstractQueue this) { * @return the head of this queue * @throws NoSuchElementException if this queue is empty */ - public E element() { + public E element(@GuardSatisfied @NonEmpty AbstractQueue this) { E x = peek(); if (x != null) return x; diff --git a/src/java.base/share/classes/java/util/ArrayDeque.java b/src/java.base/share/classes/java/util/ArrayDeque.java index c7ce65ef0af..fab432aaced 100644 --- a/src/java.base/share/classes/java/util/ArrayDeque.java +++ b/src/java.base/share/classes/java/util/ArrayDeque.java @@ -36,6 +36,10 @@ import org.checkerframework.checker.index.qual.NonNegative; 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; @@ -218,7 +222,7 @@ public ArrayDeque(@NonNegative int numElements) { * @param c the collection whose elements are to be placed into the deque * @throws NullPointerException if the specified collection is null */ - public ArrayDeque(Collection c) { + public @PolyNonEmpty ArrayDeque(@PolyNonEmpty Collection c) { this(c.size()); copyElements(c); } @@ -370,7 +374,7 @@ public boolean offerLast(E e) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeFirst(@GuardSatisfied ArrayDeque this) { + public E removeFirst(@GuardSatisfied @NonEmpty ArrayDeque this) { E e = pollFirst(); if (e == null) throw new NoSuchElementException(); @@ -380,7 +384,7 @@ public E removeFirst(@GuardSatisfied ArrayDeque this) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeLast(@GuardSatisfied ArrayDeque this) { + public E removeLast(@GuardSatisfied @NonEmpty ArrayDeque this) { E e = pollLast(); if (e == null) throw new NoSuchElementException(); @@ -410,7 +414,7 @@ public E removeLast(@GuardSatisfied ArrayDeque this) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E getFirst(@GuardSatisfied ArrayDeque this) { + public E getFirst(@GuardSatisfied @NonEmpty ArrayDeque this) { E e = elementAt(elements, head); if (e == null) throw new NoSuchElementException(); @@ -420,7 +424,7 @@ public E getFirst(@GuardSatisfied ArrayDeque this) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E getLast(@GuardSatisfied ArrayDeque this) { + public E getLast(@GuardSatisfied @NonEmpty ArrayDeque this) { final Object[] es = elements; E e = elementAt(es, dec(tail, es.length)); if (e == null) @@ -505,6 +509,7 @@ public boolean removeLastOccurrence(@GuardSatisfied ArrayDeque this, @Nullabl * @return {@code true} (as specified by {@link Collection#add}) * @throws NullPointerException if the specified element is null */ + @EnsuresNonEmpty("this") public boolean add(@GuardSatisfied ArrayDeque this, E e) { addLast(e); return true; @@ -534,7 +539,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 ArrayDeque this) { + public E remove(@GuardSatisfied @NonEmpty ArrayDeque this) { return removeFirst(); } @@ -562,7 +567,7 @@ public E remove(@GuardSatisfied ArrayDeque this) { * @return the head of the queue represented by this deque * @throws NoSuchElementException {@inheritDoc} */ - public E element() { + public E element(@GuardSatisfied @NonEmpty ArrayDeque this) { return getFirst(); } @@ -604,7 +609,7 @@ public void push(@GuardSatisfied ArrayDeque this, E e) { * of the stack represented by this deque) * @throws NoSuchElementException {@inheritDoc} */ - public E pop(@GuardSatisfied ArrayDeque this) { + public E pop(@GuardSatisfied @NonEmpty ArrayDeque this) { return removeFirst(); } @@ -672,6 +677,7 @@ boolean delete(int i) { */ @EnsuresNonNullIf(expression={"peek()", "peekFirst()", "peekLast()", "poll()", "pollFirst()", "pollLast()"}, result=false) @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty(@GuardSatisfied ArrayDeque this) { return head == tail; } @@ -685,11 +691,11 @@ public boolean isEmpty(@GuardSatisfied ArrayDeque this) { * @return an iterator over the elements in this deque */ @SideEffectFree - public Iterator iterator() { + public @PolyNonEmpty Iterator iterator(@PolyNonEmpty ArrayDeque this) { return new DeqIterator(); } - public Iterator descendingIterator() { + public @PolyNonEmpty Iterator descendingIterator(@PolyNonEmpty ArrayDeque this) { return new DescendingIterator(); } @@ -708,11 +714,12 @@ private class DeqIterator implements Iterator { DeqIterator() { cursor = head; } + @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean hasNext() { return remaining > 0; } - public E next() { + public E next(@NonEmpty DeqIterator this) { if (remaining <= 0) throw new NoSuchElementException(); final Object[] es = elements; @@ -760,7 +767,7 @@ public void forEachRemaining(Consumer action) { private class DescendingIterator extends DeqIterator { DescendingIterator() { cursor = dec(tail, elements.length); } - public final E next() { + public final E next(@NonEmpty DescendingIterator this) { if (remaining <= 0) throw new NoSuchElementException(); final Object[] es = elements; @@ -1019,6 +1026,7 @@ private boolean bulkRemoveModified( * @return {@code true} if this deque contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied ArrayDeque this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o != null) { final Object[] es = elements; diff --git a/src/java.base/share/classes/java/util/ArrayList.java b/src/java.base/share/classes/java/util/ArrayList.java index 14aca859e0c..6ba4982941e 100644 --- a/src/java.base/share/classes/java/util/ArrayList.java +++ b/src/java.base/share/classes/java/util/ArrayList.java @@ -28,6 +28,10 @@ import org.checkerframework.checker.index.qual.GTENegativeOne; import org.checkerframework.checker.index.qual.NonNegative; 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; @@ -196,7 +200,7 @@ public ArrayList() { * @throws NullPointerException if the specified collection is null */ @SideEffectFree - public ArrayList(Collection c) { + public @PolyNonEmpty ArrayList(@PolyNonEmpty Collection c) { Object[] a = c.toArray(); if ((size = a.length) != 0) { if (c.getClass() == ArrayList.class) { @@ -279,6 +283,7 @@ private Object[] grow() { * @return {@code true} if this list contains no elements */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty(@GuardSatisfied ArrayList this) { return size == 0; } @@ -293,6 +298,7 @@ public boolean isEmpty(@GuardSatisfied ArrayList this) { * @return {@code true} if this list contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied ArrayList this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { return indexOf(o) >= 0; } @@ -490,6 +496,7 @@ 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}) */ + @EnsuresNonEmpty("this") public boolean add(@GuardSatisfied ArrayList this, E e) { modCount++; add(e, elementData, size); @@ -989,12 +996,13 @@ private class Itr implements Iterator { // prevent creating a synthetic constructor Itr() {} + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") - public E next() { + public E next(@NonEmpty Itr this) { checkForComodification(); int i = cursor; if (i >= size) @@ -1305,6 +1313,7 @@ public int lastIndexOf(@GuardSatisfied @Nullable @UnknownSignedness Object o) { return index >= 0 ? index - offset : -1; } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@Nullable @UnknownSignedness Object o) { return indexOf(o) >= 0; } @@ -1323,12 +1332,13 @@ public ListIterator listIterator(@NonNegative int index) { int lastRet = -1; int expectedModCount = SubList.this.modCount; + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor != SubList.this.size; } @SuppressWarnings("unchecked") - public E next() { + public E next(/*@NonEmpty ListIterator this*/) { checkForComodification(); int i = cursor; if (i >= SubList.this.size) diff --git a/src/java.base/share/classes/java/util/Arrays.java b/src/java.base/share/classes/java/util/Arrays.java index b9c5e762b36..b3188ba6f09 100644 --- a/src/java.base/share/classes/java/util/Arrays.java +++ b/src/java.base/share/classes/java/util/Arrays.java @@ -33,6 +33,9 @@ import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.mustcall.qual.MustCallUnknown; import org.checkerframework.checker.mustcall.qual.PolyMustCall; +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.nullness.qual.PolyNull; import org.checkerframework.checker.signedness.qual.PolySigned; @@ -4168,7 +4171,7 @@ public static boolean[] copyOfRange(boolean[] original, @IndexOrHigh({"#1"}) int @SafeVarargs @SideEffectFree @SuppressWarnings("varargs") - public static List asList(T... a) { + public static @PolyNonEmpty List asList(T @PolyNonEmpty... a) { return new ArrayList<>(a); } @@ -4241,6 +4244,7 @@ public int indexOf(Object o) { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { return indexOf(o) >= 0; } @@ -4288,12 +4292,13 @@ private static class ArrayItr implements Iterator { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor < a.length; } @Override - public E next() { + public E next(@NonEmpty ArrayItr this) { int i = cursor; if (i >= a.length) { throw new NoSuchElementException(); diff --git a/src/java.base/share/classes/java/util/BitSet.java b/src/java.base/share/classes/java/util/BitSet.java index 59416e9c986..8341dfa7249 100644 --- a/src/java.base/share/classes/java/util/BitSet.java +++ b/src/java.base/share/classes/java/util/BitSet.java @@ -28,6 +28,7 @@ import org.checkerframework.checker.index.qual.GTENegativeOne; import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; @@ -885,6 +886,7 @@ public BitSet get(@GuardSatisfied BitSet this, @NonNegative int fromIndex, @NonN * @since 1.4 */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty(@GuardSatisfied BitSet this) { return wordsInUse == 0; } diff --git a/src/java.base/share/classes/java/util/Collection.java b/src/java.base/share/classes/java/util/Collection.java index 8d4991cbad2..9d6df88aa1b 100644 --- a/src/java.base/share/classes/java/util/Collection.java +++ b/src/java.base/share/classes/java/util/Collection.java @@ -27,6 +27,10 @@ import org.checkerframework.checker.index.qual.NonNegative; 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.nullness.qual.PolyNull; import org.checkerframework.checker.signedness.qual.PolySigned; @@ -282,6 +286,7 @@ public interface Collection extends Iterable { * @return {@code true} if this collection contains no elements */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") boolean isEmpty(@GuardSatisfied Collection this); /** @@ -304,6 +309,7 @@ public interface Collection extends Iterable { "Nullness: `o` is not @Nullable because this collection might forbid null", "(though I think a nicer specification would be to return false in that case)"}) @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") boolean contains(@GuardSatisfied Collection this, @GuardSatisfied @UnknownSignedness Object o); /** @@ -315,7 +321,7 @@ public interface Collection extends Iterable { * @return an {@code Iterator} over the elements in this collection */ @SideEffectFree - Iterator iterator(); + @PolyNonEmpty Iterator iterator(@PolyNonEmpty Collection this); /** * Returns an array containing all of the elements in this collection. @@ -474,6 +480,7 @@ default T[] toArray(IntFunction generator) { * @throws IllegalStateException if the element cannot be added at this * time due to insertion restrictions */ + @EnsuresNonEmpty("this") boolean add(@GuardSatisfied Collection this, E e); /** @@ -769,7 +776,7 @@ default Spliterator spliterator() { * @return a sequential {@code Stream} over the elements in this collection * @since 1.8 */ - default Stream stream() { + default @PolyNonEmpty Stream stream(@PolyNonEmpty Collection this) { return StreamSupport.stream(spliterator(), false); } diff --git a/src/java.base/share/classes/java/util/Collections.java b/src/java.base/share/classes/java/util/Collections.java index 583508a31b1..2f8182b7d99 100644 --- a/src/java.base/share/classes/java/util/Collections.java +++ b/src/java.base/share/classes/java/util/Collections.java @@ -28,6 +28,10 @@ import org.checkerframework.checker.index.qual.GTENegativeOne; import org.checkerframework.checker.index.qual.NonNegative; 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.EnsuresKeyFor; import org.checkerframework.checker.nullness.qual.EnsuresKeyForIf; import org.checkerframework.checker.nullness.qual.NonNull; @@ -99,7 +103,7 @@ * @since 1.2 */ -@AnnotatedFor({"lock", "nullness", "index"}) +@AnnotatedFor({"lock", "index", "nonempty", "nullness"}) public class Collections { // Suppresses default constructor, ensuring non-instantiability. private Collections() { @@ -1045,7 +1049,7 @@ public static boolean replaceAll(List list, @Nullable T oldVal, T newVal) */ @SuppressWarnings("unchecked") @SideEffectFree - public static Collection unmodifiableCollection(Collection c) { + public static @PolyNonEmpty Collection unmodifiableCollection(@PolyNonEmpty Collection c) { if (c.getClass() == UnmodifiableCollection.class) { return (Collection) c; } @@ -1062,7 +1066,7 @@ static class UnmodifiableCollection implements Collection, Serializable { @SuppressWarnings("serial") // Conditionally serializable final Collection c; - UnmodifiableCollection(Collection c) { + @PolyNonEmpty UnmodifiableCollection(@PolyNonEmpty Collection c) { if (c==null) throw new NullPointerException(); this.c = c; @@ -1071,8 +1075,10 @@ static class UnmodifiableCollection implements Collection, Serializable { @Pure public @NonNegative int size() {return c.size();} @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() {return c.isEmpty();} @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) {return c.contains(o);} @SideEffectFree public @PolyNull @PolySigned Object[] toArray(Collections.UnmodifiableCollection<@PolyNull @PolySigned E> this) {return c.toArray();} @@ -1082,12 +1088,13 @@ static class UnmodifiableCollection implements Collection, Serializable { public String toString() {return c.toString();} @SideEffectFree - public Iterator iterator() { + public @PolyNonEmpty Iterator iterator(@PolyNonEmpty UnmodifiableCollection this) { return new Iterator() { private final Iterator i = c.iterator(); + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() {return i.hasNext();} - public E next() {return i.next();} + public E next(/*@NonEmpty Iterator this*/) {return i.next();} public void remove() { throw new UnsupportedOperationException(); } @@ -1099,6 +1106,7 @@ public void forEachRemaining(Consumer action) { }; } + @EnsuresNonEmpty("this") public boolean add(E e) { throw new UnsupportedOperationException(); } @@ -1166,7 +1174,7 @@ public Stream parallelStream() { */ @SuppressWarnings("unchecked") @SideEffectFree - public static Set unmodifiableSet(Set s) { + public static @PolyNonEmpty Set unmodifiableSet(@PolyNonEmpty Set s) { // Not checking for subclasses because of heap pollution and information leakage. if (s.getClass() == UnmodifiableSet.class) { return (Set) s; @@ -1204,7 +1212,7 @@ static class UnmodifiableSet extends UnmodifiableCollection * returned. * @return an unmodifiable view of the specified sorted set. */ - public static SortedSet unmodifiableSortedSet(SortedSet s) { + public static @PolyNonEmpty SortedSet unmodifiableSortedSet(@PolyNonEmpty SortedSet s) { // Not checking for subclasses because of heap pollution and information leakage. if (s.getClass() == UnmodifiableSortedSet.class) { return s; @@ -1259,7 +1267,7 @@ public SortedSet tailSet(E fromElement) { * @return an unmodifiable view of the specified navigable set * @since 1.8 */ - public static NavigableSet unmodifiableNavigableSet(NavigableSet s) { + public static @PolyNonEmpty NavigableSet unmodifiableNavigableSet(@PolyNonEmpty NavigableSet s) { if (s.getClass() == UnmodifiableNavigableSet.class) { return s; } @@ -1355,7 +1363,7 @@ public NavigableSet tailSet(E fromElement, boolean inclusive) { * @return an unmodifiable view of the specified list. */ @SuppressWarnings("unchecked") - public static List unmodifiableList(List list) { + public static @PolyNonEmpty List unmodifiableList(@PolyNonEmpty List list) { if (list.getClass() == UnmodifiableList.class || list.getClass() == UnmodifiableRandomAccessList.class) { return (List) list; } @@ -1409,15 +1417,16 @@ public void sort(Comparator c) { throw new UnsupportedOperationException(); } - public ListIterator listIterator() {return listIterator(0);} + public @PolyNonEmpty ListIterator listIterator(@PolyNonEmpty UnmodifiableList this) {return listIterator(0);} public ListIterator listIterator(final int index) { return new ListIterator() { private final ListIterator i = list.listIterator(index); + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() {return i.hasNext();} - public E next() {return i.next();} + public E next(/*@NonEmpty ListIterator this*/) {return i.next();} public boolean hasPrevious() {return i.hasPrevious();} public E previous() {return i.previous();} public int nextIndex() {return i.nextIndex();} @@ -1511,7 +1520,7 @@ private Object writeReplace() { * @return an unmodifiable view of the specified map. */ @SuppressWarnings("unchecked") - public static Map unmodifiableMap(Map m) { + public static @PolyNonEmpty Map unmodifiableMap(@PolyNonEmpty Map m) { // Not checking for subclasses because of heap pollution and information leakage. if (m.getClass() == UnmodifiableMap.class) { return (Map) m; @@ -1538,6 +1547,7 @@ private static class UnmodifiableMap implements Map, Serializable { @Pure public @NonNegative int size() {return m.size();} @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() {return m.isEmpty();} @Pure @EnsuresKeyForIf(expression={"#1"}, result=true, map={"this"}) @@ -1753,10 +1763,11 @@ public Iterator> iterator() { return new Iterator>() { private final Iterator> i = c.iterator(); + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return i.hasNext(); } - public Map.Entry next() { + public Map.Entry next(/*@NonEmpty Iterator> this*/) { return new UnmodifiableEntry<>(i.next()); } public void remove() { @@ -1801,6 +1812,7 @@ public Object[] toArray() { * that the equality-candidate is Map.Entry and calls its * setValue method. */ + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { if (!(o instanceof Map.Entry)) return false; @@ -1880,7 +1892,7 @@ && eq(e.getKey(), t.getKey()) * @return an unmodifiable view of the specified sorted map. */ @SuppressWarnings("unchecked") - public static SortedMap unmodifiableSortedMap(SortedMap m) { + public static @PolyNonEmpty SortedMap unmodifiableSortedMap(@PolyNonEmpty SortedMap m) { // Not checking for subclasses because of heap pollution and information leakage. if (m.getClass() == UnmodifiableSortedMap.class) { return (SortedMap) m; @@ -1935,7 +1947,7 @@ public SortedMap tailMap(K fromKey) * @since 1.8 */ @SuppressWarnings("unchecked") - public static NavigableMap unmodifiableNavigableMap(NavigableMap m) { + public static @PolyNonEmpty NavigableMap unmodifiableNavigableMap(@PolyNonEmpty NavigableMap m) { if (m.getClass() == UnmodifiableNavigableMap.class) { return (NavigableMap) m; } @@ -2142,10 +2154,12 @@ static class SynchronizedCollection implements Collection, Serializable { synchronized (mutex) {return c.size();} } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { synchronized (mutex) {return c.isEmpty();} } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { synchronized (mutex) {return c.contains(o);} } @@ -2166,6 +2180,7 @@ public Iterator iterator() { return c.iterator(); // Must be manually synched by user! } + @EnsuresNonEmpty("this") public boolean add(E e) { synchronized (mutex) {return c.add(e);} } @@ -2729,6 +2744,7 @@ private static class SynchronizedMap synchronized (mutex) {return m.size();} } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { synchronized (mutex) {return m.isEmpty();} } @@ -3238,8 +3254,10 @@ private String badElementMsg(Object o) { @Pure public @NonNegative int size() { return c.size(); } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return c.isEmpty(); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { return c.contains(o); } @SideEffectFree public @PolyNull @PolySigned Object[] toArray(Collections.CheckedCollection<@PolyNull @PolySigned E> this) { return c.toArray(); } @@ -3267,8 +3285,9 @@ public Iterator iterator() { // ListIterator with unsafe set() final Iterator it = c.iterator(); return new Iterator() { + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return it.hasNext(); } - public E next() { return it.next(); } + public E next(/*@NonEmpty Iterator this*/) { return it.next(); } public void remove() { it.remove(); } public void forEachRemaining(Consumer action) { it.forEachRemaining(action); @@ -3276,6 +3295,7 @@ public void forEachRemaining(Consumer action) { }; } + @EnsuresNonEmpty("this") public boolean add(E e) { return c.add(typeCheck(e)); } @SuppressWarnings("serial") // Conditionally serializable @@ -3659,8 +3679,9 @@ public ListIterator listIterator(final int index) { final ListIterator i = list.listIterator(index); return new ListIterator() { + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return i.hasNext(); } - public E next() { return i.next(); } + public E next(/*@NonEmpty ListIterator this*/) { return i.next(); } public boolean hasPrevious() { return i.hasPrevious(); } public E previous() { return i.previous(); } public int nextIndex() { return i.nextIndex(); } @@ -3821,6 +3842,7 @@ private String badValueMsg(Object value) { @Pure public @NonNegative int size() { return m.size(); } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return m.isEmpty(); } @Pure @EnsuresKeyForIf(expression={"#1"}, result=true, map={"this"}) @@ -3961,11 +3983,13 @@ static class CheckedEntrySet implements Set> { @Pure public int size() { return s.size(); } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return s.isEmpty(); } public String toString() { return s.toString(); } public int hashCode() { return s.hashCode(); } public void clear() { s.clear(); } + @EnsuresNonEmpty("this") public boolean add(Map.Entry e) { throw new UnsupportedOperationException(); } @@ -3977,10 +4001,11 @@ public Iterator> iterator() { final Iterator> i = s.iterator(); return new Iterator>() { + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return i.hasNext(); } public void remove() { i.remove(); } - public Map.Entry next() { + public Map.Entry next(/*@NonEmpty Iterator> this*/) { return checkedEntry(i.next(), valueType); } @@ -4035,6 +4060,7 @@ public Object[] toArray() { * setValue method. */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { return o instanceof Map.Entry e && s.contains((e instanceof CheckedEntry) ? e : checkedEntry(e, valueType)); @@ -4428,9 +4454,10 @@ private static class EmptyIterator implements Iterator { static final EmptyIterator EMPTY_ITERATOR = new EmptyIterator<>(); + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return false; } - public E next() { throw new NoSuchElementException(); } - public void remove() { throw new IllegalStateException(); } + public E next(@NonEmpty EmptyIterator this) { throw new NoSuchElementException(); } + public void remove(@NonEmpty EmptyIterator this) { throw new IllegalStateException(); } @Override public void forEachRemaining(Consumer action) { Objects.requireNonNull(action); @@ -4511,8 +4538,9 @@ private static class EmptyEnumeration implements Enumeration { static final EmptyEnumeration EMPTY_ENUMERATION = new EmptyEnumeration<>(); + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasMoreElements() { return false; } - public E nextElement() { throw new NoSuchElementException(); } + public E nextElement(@NonEmpty EmptyEnumeration this) { throw new NoSuchElementException(); } public Iterator asIterator() { return emptyIterator(); } } @@ -4565,10 +4593,12 @@ private static class EmptySet @Pure public @NonNegative int size() {return 0;} @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() {return true;} public void clear() {} @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object obj) {return false;} @Pure public boolean containsAll(Collection c) { return c.isEmpty(); } @@ -4707,10 +4737,12 @@ public ListIterator listIterator() { @Pure public @NonNegative int size() {return 0;} @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() {return true;} public void clear() {} @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object obj) {return false;} @Pure public boolean containsAll(Collection c) { return c.isEmpty(); } @@ -4855,6 +4887,7 @@ private static class EmptyMap @Pure public @NonNegative int size() {return 0;} @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() {return true;} public void clear() {} @Pure @@ -4961,10 +4994,11 @@ public static Set singleton(T o) { static Iterator singletonIterator(final E e) { return new Iterator() { private boolean hasNext = true; + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return hasNext; } - public E next() { + public E next(/*@NonEmpty Iterator this*/) { if (hasNext) { hasNext = false; return e; @@ -5055,6 +5089,7 @@ public Iterator iterator() { public @NonNegative int size() {return 1;} @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) {return eq(o, element);} // Override default methods for Collection @@ -5116,6 +5151,7 @@ public Iterator iterator() { public @NonNegative int size() {return 1;} @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object obj) {return eq(obj, element);} public E get(int index) { @@ -5189,6 +5225,7 @@ private static class SingletonMap @Pure public @NonNegative int size() {return 1;} @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() {return false;} @Pure @EnsuresKeyForIf(expression={"#1"}, result=true, map={"this"}) @@ -5340,6 +5377,7 @@ private static class CopiesList } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object obj) { return n != 0 && eq(obj, element); } @@ -5610,11 +5648,12 @@ public static Enumeration enumeration(final Collection c) { return new Enumeration() { private final Iterator i = c.iterator(); + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasMoreElements() { return i.hasNext(); } - public T nextElement() { + public T nextElement(/*@NonEmpty Enumeration this*/) { return i.next(); } }; @@ -5860,10 +5899,13 @@ private static class SetFromMap extends AbstractSet @Pure public @NonNegative int size() { return m.size(); } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return m.isEmpty(); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { return m.containsKey(o); } public boolean remove(@UnknownSignedness Object o) { return m.remove(o) != null; } + @EnsuresNonEmpty("this") public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; } @SideEffectFree public Iterator iterator() { return s.iterator(); } @@ -5942,6 +5984,7 @@ static class AsLIFOQueue extends AbstractQueue @SuppressWarnings("serial") // Conditionally serializable private final Deque q; AsLIFOQueue(Deque q) { this.q = q; } + @EnsuresNonEmpty("this") public boolean add(E e) { q.addFirst(e); return true; } public boolean offer(E e) { return q.offerFirst(e); } public E poll() { return q.pollFirst(); } @@ -5952,8 +5995,10 @@ static class AsLIFOQueue extends AbstractQueue @Pure public @NonNegative int size() { return q.size(); } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return q.isEmpty(); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { return q.contains(o); } public boolean remove(@UnknownSignedness Object o) { return q.remove(o); } @SideEffectFree diff --git a/src/java.base/share/classes/java/util/Deque.java b/src/java.base/share/classes/java/util/Deque.java index b194de7a8c0..c538662e94b 100644 --- a/src/java.base/share/classes/java/util/Deque.java +++ b/src/java.base/share/classes/java/util/Deque.java @@ -35,10 +35,13 @@ package java.util; -import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.checker.index.qual.NonNegative; 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.nullness.qual.Nullable; +import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -230,6 +233,7 @@ public interface Deque extends Queue { * @throws IllegalArgumentException if some property of the specified * element prevents it from being added to this deque */ + @EnsuresNonEmpty("this") void addFirst(@GuardSatisfied Deque this, E e); /** @@ -251,6 +255,7 @@ public interface Deque extends Queue { * @throws IllegalArgumentException if some property of the specified * element prevents it from being added to this deque */ + @EnsuresNonEmpty("this") void addLast(@GuardSatisfied Deque this, E e); /** @@ -297,7 +302,7 @@ public interface Deque extends Queue { * @return the head of this deque * @throws NoSuchElementException if this deque is empty */ - E removeFirst(@GuardSatisfied Deque this); + E removeFirst(@GuardSatisfied @NonEmpty Deque this); /** * Retrieves and removes the last element of this deque. This method @@ -307,7 +312,7 @@ public interface Deque extends Queue { * @return the tail of this deque * @throws NoSuchElementException if this deque is empty */ - E removeLast(@GuardSatisfied Deque this); + E removeLast(@GuardSatisfied @NonEmpty Deque this); /** * Retrieves and removes the first element of this deque, @@ -334,7 +339,8 @@ public interface Deque extends Queue { * @return the head of this deque * @throws NoSuchElementException if this deque is empty */ - E getFirst(@GuardSatisfied Deque this); + @EnsuresNonEmpty("this") + E getFirst(@GuardSatisfied @NonEmpty Deque this); /** * Retrieves, but does not remove, the last element of this deque. @@ -344,7 +350,8 @@ public interface Deque extends Queue { * @return the tail of this deque * @throws NoSuchElementException if this deque is empty */ - E getLast(@GuardSatisfied Deque this); + @EnsuresNonEmpty("this") + E getLast(@GuardSatisfied @NonEmpty Deque this); /** * Retrieves, but does not remove, the first element of this deque, @@ -424,6 +431,7 @@ public interface Deque extends Queue { * @throws IllegalArgumentException if some property of the specified * element prevents it from being added to this deque */ + @EnsuresNonEmpty("this") boolean add(@GuardSatisfied Deque this, E e); /** @@ -460,7 +468,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 Deque this); + E remove(@GuardSatisfied @NonEmpty Deque this); /** * Retrieves and removes the head of the queue represented by this deque @@ -485,7 +493,7 @@ public interface Deque extends Queue { * @return the head of the queue represented by this deque * @throws NoSuchElementException if this deque is empty */ - E element(); + E element(@GuardSatisfied @NonEmpty Deque this); /** * Retrieves, but does not remove, the head of the queue represented by @@ -557,7 +565,7 @@ public interface Deque extends Queue { * of the stack represented by this deque) * @throws NoSuchElementException if this deque is empty */ - E pop(@GuardSatisfied Deque this); + E pop(@GuardSatisfied @NonEmpty Deque this); // *** Collection methods *** @@ -598,6 +606,7 @@ public interface Deque extends Queue { * (optional) */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") boolean contains(@GuardSatisfied Deque this, @UnknownSignedness Object o); /** diff --git a/src/java.base/share/classes/java/util/Dictionary.java b/src/java.base/share/classes/java/util/Dictionary.java index b3c063af9e6..95eccfffbfd 100644 --- a/src/java.base/share/classes/java/util/Dictionary.java +++ b/src/java.base/share/classes/java/util/Dictionary.java @@ -27,6 +27,7 @@ import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nullness.qual.EnsuresKeyFor; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.signedness.qual.UnknownSignedness; @@ -82,6 +83,7 @@ public Dictionary() { * {@code false} otherwise. */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public abstract boolean isEmpty(@GuardSatisfied Dictionary this); /** diff --git a/src/java.base/share/classes/java/util/EnumMap.java b/src/java.base/share/classes/java/util/EnumMap.java index 2018e3a331b..78bad1dc660 100644 --- a/src/java.base/share/classes/java/util/EnumMap.java +++ b/src/java.base/share/classes/java/util/EnumMap.java @@ -28,6 +28,8 @@ import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.initialization.qual.UnknownInitialization; 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.nullness.qual.EnsuresKeyFor; import org.checkerframework.checker.nullness.qual.EnsuresKeyForIf; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; @@ -419,6 +421,7 @@ public Iterator iterator() { return size; } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@Nullable @UnknownSignedness Object o) { return containsKey(o); } @@ -461,6 +464,7 @@ public Iterator iterator() { return size; } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@Nullable @UnknownSignedness Object o) { return containsValue(o); } @@ -506,6 +510,7 @@ public Iterator> iterator() { } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@Nullable @UnknownSignedness Object o) { return o instanceof Map.Entry entry && containsMapping(entry.getKey(), entry.getValue()); @@ -562,6 +567,7 @@ private abstract class EnumMapIterator implements Iterator { // Index of last returned element, or -1 if none int lastReturnedIndex = -1; + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { while (index < vals.length && vals[index] == null) index++; @@ -585,7 +591,7 @@ private void checkLastReturnedIndex() { } private class KeyIterator extends EnumMapIterator { - public K next() { + public K next(@NonEmpty KeyIterator this) { if (!hasNext()) throw new NoSuchElementException(); lastReturnedIndex = index++; @@ -597,7 +603,7 @@ private class ValueIterator extends EnumMapIterator { @CFComment({"nullness: Value returned by unmaskNull", "will be of type V (not @Nullable V) for mapped value"}) @SuppressWarnings({"nullness:return"}) - public V next() { + public V next(@NonEmpty ValueIterator this) { if (!hasNext()) throw new NoSuchElementException(); lastReturnedIndex = index++; @@ -608,7 +614,7 @@ public V next() { private class EntryIterator extends EnumMapIterator> { private Entry lastReturnedEntry; - public Map.Entry next() { + public Map.Entry next(@NonEmpty EntryIterator this) { if (!hasNext()) throw new NoSuchElementException(); lastReturnedEntry = new Entry(index++); diff --git a/src/java.base/share/classes/java/util/Enumeration.java b/src/java.base/share/classes/java/util/Enumeration.java index 6af0fa7bc91..0f42fa94e1c 100644 --- a/src/java.base/share/classes/java/util/Enumeration.java +++ b/src/java.base/share/classes/java/util/Enumeration.java @@ -25,6 +25,9 @@ package java.util; +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.framework.qual.AnnotatedFor; @@ -74,6 +77,7 @@ public interface Enumeration { * {@code false} otherwise. */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") boolean hasMoreElements(); /** @@ -83,7 +87,7 @@ public interface Enumeration { * @return the next element of this enumeration. * @throws NoSuchElementException if no more elements exist. */ - E nextElement(); + E nextElement(@GuardSatisfied @NonEmpty Enumeration this); /** * Returns an {@link Iterator} that traverses the remaining elements @@ -121,10 +125,11 @@ public interface Enumeration { */ default Iterator asIterator() { return new Iterator<>() { + @EnsuresNonEmptyIf(result = true, expression = "this") @Override public boolean hasNext() { return hasMoreElements(); } - @Override public E next() { + @Override public E next(/*@NonEmpty Iterator this*/) { return nextElement(); } }; diff --git a/src/java.base/share/classes/java/util/Formatter.java b/src/java.base/share/classes/java/util/Formatter.java index c15d2906f17..421e0687911 100644 --- a/src/java.base/share/classes/java/util/Formatter.java +++ b/src/java.base/share/classes/java/util/Formatter.java @@ -27,6 +27,7 @@ import org.checkerframework.checker.formatter.qual.FormatMethod; import org.checkerframework.checker.mustcall.qual.MustCallAlias; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.framework.qual.AnnotatedFor; @@ -4603,6 +4604,7 @@ public int valueOf() { } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(Flags f) { return (flags & f.valueOf()) == f.valueOf(); } diff --git a/src/java.base/share/classes/java/util/HashMap.java b/src/java.base/share/classes/java/util/HashMap.java index 5076d384796..ef22aa82d95 100644 --- a/src/java.base/share/classes/java/util/HashMap.java +++ b/src/java.base/share/classes/java/util/HashMap.java @@ -27,6 +27,9 @@ import org.checkerframework.checker.index.qual.NonNegative; 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.EnsuresKeyFor; import org.checkerframework.checker.nullness.qual.EnsuresKeyForIf; import org.checkerframework.checker.nullness.qual.KeyFor; @@ -493,7 +496,7 @@ public HashMap() { * @param m the map whose mappings are to be placed in this map * @throws NullPointerException if the specified map is null */ - public HashMap(Map m) { + public @PolyNonEmpty HashMap(@PolyNonEmpty Map m) { this.loadFactor = DEFAULT_LOAD_FACTOR; putMapEntries(m, false); } @@ -546,6 +549,7 @@ final void putMapEntries(Map m, boolean evict) { * @return {@code true} if this map contains no key-value mappings */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty(@GuardSatisfied HashMap this) { return size == 0; } @@ -1007,6 +1011,7 @@ final class KeySet extends AbstractSet { @SideEffectFree public final Iterator iterator() { return new KeyIterator(); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean contains(@Nullable @UnknownSignedness Object o) { return containsKey(o); } public final boolean remove(@Nullable @UnknownSignedness Object key) { return removeNode(hash(key), key, null, false, true) != null; @@ -1072,6 +1077,7 @@ final class Values extends AbstractCollection { @SideEffectFree public final Iterator iterator() { return new ValueIterator(); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean contains(@Nullable @UnknownSignedness Object o) { return containsValue(o); } @SideEffectFree public final Spliterator spliterator() { @@ -1133,6 +1139,7 @@ public final Iterator> iterator() { return new EntryIterator(); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean contains(@Nullable @UnknownSignedness Object o) { if (!(o instanceof Map.Entry e)) return false; @@ -1609,11 +1616,12 @@ abstract class HashIterator { } } + @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean hasNext() { return next != null; } - final Node nextNode() { + final Node nextNode(@NonEmpty HashIterator this) { Node[] t; Node e = next; if (modCount != expectedModCount) @@ -1640,17 +1648,17 @@ public final void remove() { final class KeyIterator extends HashIterator implements Iterator { - public final K next() { return nextNode().key; } + public final K next(@NonEmpty KeyIterator this) { return nextNode().key; } } final class ValueIterator extends HashIterator implements Iterator { - public final V next() { return nextNode().value; } + public final V next(@NonEmpty ValueIterator this) { return nextNode().value; } } final class EntryIterator extends HashIterator implements Iterator> { - public final Map.Entry next() { return nextNode(); } + public final Map.Entry next(@NonEmpty EntryIterator this) { return nextNode(); } } /* ------------------------------------------------------------ */ diff --git a/src/java.base/share/classes/java/util/HashSet.java b/src/java.base/share/classes/java/util/HashSet.java index 3d6fd82484f..60c0692c5c2 100644 --- a/src/java.base/share/classes/java/util/HashSet.java +++ b/src/java.base/share/classes/java/util/HashSet.java @@ -27,6 +27,10 @@ import org.checkerframework.checker.index.qual.NonNegative; 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.nullness.qual.PolyNull; import org.checkerframework.checker.signedness.qual.UnknownSignedness; @@ -126,7 +130,7 @@ public HashSet() { * @param c the collection whose elements are to be placed into this set * @throws NullPointerException if the specified collection is null */ - public HashSet(Collection c) { + public @PolyNonEmpty HashSet(@PolyNonEmpty Collection c) { map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); } @@ -181,7 +185,7 @@ public HashSet(@NonNegative int initialCapacity) { * @see ConcurrentModificationException */ @SideEffectFree - public Iterator iterator() { + public @PolyNonEmpty Iterator iterator(@PolyNonEmpty HashSet this) { return map.keySet().iterator(); } @@ -201,6 +205,7 @@ public Iterator iterator() { * @return {@code true} if this set contains no elements */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty(@GuardSatisfied HashSet this) { return map.isEmpty(); } @@ -215,6 +220,7 @@ public boolean isEmpty(@GuardSatisfied HashSet this) { * @return {@code true} if this set contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied HashSet this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { return map.containsKey(o); } @@ -231,6 +237,7 @@ public boolean contains(@GuardSatisfied HashSet this, @GuardSatisfied @Nullab * @return {@code true} if this set did not already contain the specified * element */ + @EnsuresNonEmpty("this") public boolean add(@GuardSatisfied HashSet this, E e) { return map.put(e, PRESENT)==null; } diff --git a/src/java.base/share/classes/java/util/Hashtable.java b/src/java.base/share/classes/java/util/Hashtable.java index 134c014a588..3879f699979 100644 --- a/src/java.base/share/classes/java/util/Hashtable.java +++ b/src/java.base/share/classes/java/util/Hashtable.java @@ -27,6 +27,9 @@ import org.checkerframework.checker.index.qual.NonNegative; 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.nullness.qual.EnsuresKeyFor; import org.checkerframework.checker.nullness.qual.EnsuresKeyForIf; import org.checkerframework.checker.nullness.qual.KeyFor; @@ -272,6 +275,7 @@ public Hashtable(Map t) { * {@code false} otherwise. */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public synchronized boolean isEmpty(@GuardSatisfied Hashtable this) { return count == 0; } @@ -325,6 +329,7 @@ public synchronized Enumeration elements() { * @throws NullPointerException if the value is {@code null} */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public synchronized boolean contains(@GuardSatisfied Hashtable this, @GuardSatisfied @UnknownSignedness Object value) { if (value == null) { throw new NullPointerException(); @@ -700,6 +705,7 @@ public Iterator iterator() { return count; } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { return containsKey(o); } @@ -740,11 +746,13 @@ public Iterator> iterator() { return getIterator(ENTRIES); } + @EnsuresNonEmpty("this") public boolean add(Map.Entry o) { return super.add(o); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { if (!(o instanceof Map.Entry entry)) return false; @@ -828,6 +836,7 @@ public Iterator iterator() { return count; } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { return containsValue(o); } @@ -1485,6 +1494,7 @@ private class Enumerator implements Enumeration, Iterator { this.iterator = iterator; } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasMoreElements() { Entry e = entry; int i = index; @@ -1499,7 +1509,7 @@ public boolean hasMoreElements() { } @SuppressWarnings("unchecked") - public T nextElement() { + public T nextElement(@NonEmpty Enumerator this) { Entry et = entry; int i = index; Entry[] t = table; @@ -1518,11 +1528,12 @@ public T nextElement() { } // Iterator methods + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return hasMoreElements(); } - public T next() { + public T next(@NonEmpty Enumerator this) { if (Hashtable.this.modCount != expectedModCount) throw new ConcurrentModificationException(); return nextElement(); diff --git a/src/java.base/share/classes/java/util/IdentityHashMap.java b/src/java.base/share/classes/java/util/IdentityHashMap.java index 5c922f8ec96..76c77d0f977 100644 --- a/src/java.base/share/classes/java/util/IdentityHashMap.java +++ b/src/java.base/share/classes/java/util/IdentityHashMap.java @@ -27,6 +27,8 @@ import org.checkerframework.checker.index.qual.NonNegative; 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.nullness.qual.EnsuresKeyFor; import org.checkerframework.checker.nullness.qual.EnsuresKeyForIf; import org.checkerframework.checker.nullness.qual.KeyFor; @@ -303,6 +305,7 @@ public IdentityHashMap(Map m) { * mappings */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty(@GuardSatisfied IdentityHashMap this) { return size == 0; } @@ -742,6 +745,7 @@ private abstract class IdentityHashMapIterator implements Iterator { boolean indexValid; // To avoid unnecessary next computation Object[] traversalTable = table; // reference to main table or copy + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { Object[] tab = traversalTable; for (int i = index; i < tab.length; i+=2) { @@ -755,7 +759,7 @@ public boolean hasNext() { return false; } - protected int nextIndex() { + protected int nextIndex(@NonEmpty IdentityHashMapIterator this) { if (modCount != expectedModCount) throw new ConcurrentModificationException(); if (!indexValid && !hasNext()) @@ -847,14 +851,14 @@ public void remove() { private class KeyIterator extends IdentityHashMapIterator { @SuppressWarnings("unchecked") - public K next() { + public K next(@NonEmpty KeyIterator this) { return (K) unmaskNull(traversalTable[nextIndex()]); } } private class ValueIterator extends IdentityHashMapIterator { @SuppressWarnings("unchecked") - public V next() { + public V next(@NonEmpty ValueIterator this) { return (V) traversalTable[nextIndex() + 1]; } } @@ -864,7 +868,7 @@ private class EntryIterator { private Entry lastReturnedEntry; - public Map.Entry next() { + public Map.Entry next(@NonEmpty EntryIterator this) { lastReturnedEntry = new Entry(nextIndex()); return lastReturnedEntry; } @@ -1006,6 +1010,7 @@ public Iterator iterator() { return size; } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@Nullable @UnknownSignedness Object o) { return containsKey(o); } @@ -1119,6 +1124,7 @@ public Iterator iterator() { return size; } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@Nullable @UnknownSignedness Object o) { return containsValue(o); } @@ -1226,6 +1232,7 @@ public Iterator> iterator() { return new EntryIterator(); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@Nullable @UnknownSignedness Object o) { return o instanceof Entry entry && containsMapping(entry.getKey(), entry.getValue()); diff --git a/src/java.base/share/classes/java/util/ImmutableCollections.java b/src/java.base/share/classes/java/util/ImmutableCollections.java index e0a23febde0..0229f0efefd 100644 --- a/src/java.base/share/classes/java/util/ImmutableCollections.java +++ b/src/java.base/share/classes/java/util/ImmutableCollections.java @@ -25,6 +25,9 @@ package java.util; +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.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -151,7 +154,9 @@ private ImmutableCollections() { } @jdk.internal.ValueBased static abstract class AbstractImmutableCollection extends AbstractCollection { // all mutating methods throw UnsupportedOperationException - @Override public boolean add(E e) { throw uoe(); } + @Override + @EnsuresNonEmpty("this") + public boolean add(E e) { throw uoe(); } @Override public boolean addAll(Collection c) { throw uoe(); } @Override public void clear() { throw uoe(); } @Override public boolean remove(@UnknownSignedness Object o) { throw uoe(); } @@ -333,6 +338,7 @@ public int hashCode() { @Override @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { return indexOf(o) >= 0; } @@ -369,11 +375,12 @@ static final class ListItr implements ListIterator { isListIterator = true; } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor != size; } - public E next() { + public E next(@NonEmpty ListItr this) { try { int i = cursor; E next = list.get(i); @@ -580,6 +587,7 @@ public int size() { } @Override + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return false; } @@ -677,6 +685,7 @@ private ListN(E[] elements, boolean allowNulls) { @Pure @Override + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return elements.length == 0; } @@ -814,12 +823,14 @@ public int size() { } @Override + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return false; } @Override @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { return o.equals(e0) || e1.equals(o); // implicit nullcheck of o } @@ -831,17 +842,18 @@ public int hashCode() { @Override public Iterator iterator() { - return new Iterator<>() { + return new Iterator() { private int idx = (e1 == EMPTY) ? 1 : 2; @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return idx > 0; } @Override @SuppressWarnings("unchecked") - public E next() { + public E next(/*@NonEmpty Iterator this*/) { if (idx == 1) { idx = 0; return (REVERSE || e1 == EMPTY) ? e0 : (E)e1; @@ -943,12 +955,14 @@ public int size() { } @Override + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return size == 0; } @Override @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { Objects.requireNonNull(o); return size > 0 && probe(o) >= 0; @@ -968,12 +982,13 @@ private final class SetNIterator implements Iterator { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return remaining > 0; } @Override - public E next() { + public E next(@NonEmpty SetNIterator this) { if (remaining > 0) { E element; int idx = this.idx; @@ -1150,6 +1165,7 @@ public int size() { } @Override + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return false; } @@ -1268,6 +1284,7 @@ public int size() { } @Override + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return size == 0; } @@ -1286,6 +1303,7 @@ class MapNIterator implements Iterator> { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return remaining > 0; } @@ -1305,7 +1323,7 @@ private int nextIndex() { } @Override - public Map.Entry next() { + public Map.Entry next(@NonEmpty MapNIterator this) { if (remaining > 0) { int idx; while (table[idx = nextIndex()] == null) {} diff --git a/src/java.base/share/classes/java/util/Iterator.java b/src/java.base/share/classes/java/util/Iterator.java index 42784d41181..1e0d65349c6 100644 --- a/src/java.base/share/classes/java/util/Iterator.java +++ b/src/java.base/share/classes/java/util/Iterator.java @@ -26,6 +26,8 @@ package java.util; 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.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -75,6 +77,7 @@ public interface Iterator { * @return {@code true} if the iteration has more elements */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") boolean hasNext(@GuardSatisfied Iterator this); /** @@ -83,7 +86,7 @@ public interface Iterator { * @return the next element in the iteration * @throws NoSuchElementException if the iteration has no more elements */ - E next(@GuardSatisfied Iterator this); + E next(@GuardSatisfied @NonEmpty Iterator this); /** * Removes from the underlying collection the last element returned diff --git a/src/java.base/share/classes/java/util/JumboEnumSet.java b/src/java.base/share/classes/java/util/JumboEnumSet.java index 045b2ba4f92..0a1e008a1ea 100644 --- a/src/java.base/share/classes/java/util/JumboEnumSet.java +++ b/src/java.base/share/classes/java/util/JumboEnumSet.java @@ -26,6 +26,9 @@ package java.util; 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.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -136,6 +139,7 @@ private class EnumSetIterator> implements Iterator { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { while (unseen == 0 && unseenIndex < elements.length - 1) unseen = elements[++unseenIndex]; @@ -144,7 +148,7 @@ public boolean hasNext() { @Override @SuppressWarnings("unchecked") - public E next() { + public E next(@NonEmpty EnumSetIterator this) { if (!hasNext()) throw new NoSuchElementException(); lastReturned = unseen & -unseen; @@ -183,6 +187,7 @@ public void remove() { * @return {@code true} if this set contains no elements */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return size == 0; } @@ -194,6 +199,7 @@ public boolean isEmpty() { * @return {@code true} if this set contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied @Nullable @UnknownSignedness Object e) { if (e == null) return false; @@ -215,6 +221,7 @@ public boolean contains(@GuardSatisfied @Nullable @UnknownSignedness Object e) { * * @throws NullPointerException if {@code e} is null */ + @EnsuresNonEmpty("this") public boolean add(E e) { typeCheck(e); diff --git a/src/java.base/share/classes/java/util/LinkedHashMap.java b/src/java.base/share/classes/java/util/LinkedHashMap.java index cd86536cf50..50be45dd72b 100644 --- a/src/java.base/share/classes/java/util/LinkedHashMap.java +++ b/src/java.base/share/classes/java/util/LinkedHashMap.java @@ -27,6 +27,9 @@ import org.checkerframework.checker.index.qual.NonNegative; 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.KeyFor; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -390,7 +393,7 @@ public LinkedHashMap() { * @param m the map whose mappings are to be placed in this map * @throws NullPointerException if the specified map is null */ - public LinkedHashMap(Map m) { + public @PolyNonEmpty LinkedHashMap(@PolyNonEmpty Map m) { super(); accessOrder = false; putMapEntries(m, false); @@ -581,6 +584,7 @@ public final Iterator iterator() { return new LinkedKeyIterator(); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean contains(@Nullable @UnknownSignedness Object o) { return containsKey(o); } public final boolean remove(@Nullable @UnknownSignedness Object key) { return removeNode(hash(key), key, null, false, true) != null; @@ -647,6 +651,7 @@ public final Iterator iterator() { return new LinkedValueIterator(); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean contains(@Nullable @UnknownSignedness Object o) { return containsValue(o); } @SideEffectFree public final Spliterator spliterator() { @@ -707,6 +712,7 @@ public final Iterator> iterator() { return new LinkedEntryIterator(); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean contains(@Nullable @UnknownSignedness Object o) { if (!(o instanceof Map.Entry e)) return false; @@ -774,11 +780,12 @@ abstract class LinkedHashIterator { current = null; } + @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean hasNext() { return next != null; } - final LinkedHashMap.Entry nextNode() { + final LinkedHashMap.Entry nextNode(@NonEmpty LinkedHashIterator this) { LinkedHashMap.Entry e = next; if (modCount != expectedModCount) throw new ConcurrentModificationException(); @@ -803,17 +810,17 @@ public final void remove() { final class LinkedKeyIterator extends LinkedHashIterator implements Iterator { - public final K next() { return nextNode().getKey(); } + public final K next(@NonEmpty LinkedKeyIterator this) { return nextNode().getKey(); } } final class LinkedValueIterator extends LinkedHashIterator implements Iterator { - public final V next() { return nextNode().value; } + public final V next(@NonEmpty LinkedValueIterator this) { return nextNode().value; } } final class LinkedEntryIterator extends LinkedHashIterator implements Iterator> { - public final Map.Entry next() { return nextNode(); } + public final Map.Entry next(@NonEmpty LinkedEntryIterator this) { return nextNode(); } } diff --git a/src/java.base/share/classes/java/util/LinkedList.java b/src/java.base/share/classes/java/util/LinkedList.java index a32b7ae1e74..b1b0db89f7c 100644 --- a/src/java.base/share/classes/java/util/LinkedList.java +++ b/src/java.base/share/classes/java/util/LinkedList.java @@ -29,6 +29,10 @@ import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.lock.qual.ReleasesNoLocks; +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.nullness.qual.PolyNull; import org.checkerframework.checker.signedness.qual.PolySigned; @@ -133,7 +137,7 @@ public LinkedList() { * @param c the collection whose elements are to be placed into this list * @throws NullPointerException if the specified collection is null */ - public LinkedList(Collection c) { + public @PolyNonEmpty LinkedList(@PolyNonEmpty Collection c) { this(); addAll(c); } @@ -257,7 +261,7 @@ E unlink(Node x) { * @return the first element in this list * @throws NoSuchElementException if this list is empty */ - public E getFirst(@GuardSatisfied LinkedList this) { + public E getFirst(@GuardSatisfied @NonEmpty LinkedList this) { final Node f = first; if (f == null) throw new NoSuchElementException(); @@ -270,7 +274,7 @@ public E getFirst(@GuardSatisfied LinkedList this) { * @return the last element in this list * @throws NoSuchElementException if this list is empty */ - public E getLast(@GuardSatisfied LinkedList this) { + public E getLast(@GuardSatisfied @NonEmpty LinkedList this) { final Node l = last; if (l == null) throw new NoSuchElementException(); @@ -283,7 +287,7 @@ public E getLast(@GuardSatisfied LinkedList this) { * @return the first element from this list * @throws NoSuchElementException if this list is empty */ - public E removeFirst(@GuardSatisfied LinkedList this) { + public E removeFirst(@GuardSatisfied @NonEmpty LinkedList this) { final Node f = first; if (f == null) throw new NoSuchElementException(); @@ -296,7 +300,7 @@ public E removeFirst(@GuardSatisfied LinkedList this) { * @return the last element from this list * @throws NoSuchElementException if this list is empty */ - public E removeLast(@GuardSatisfied LinkedList this) { + public E removeLast(@GuardSatisfied @NonEmpty LinkedList this) { final Node l = last; if (l == null) throw new NoSuchElementException(); @@ -333,6 +337,7 @@ public void addLast(@GuardSatisfied LinkedList this, E e) { * @return {@code true} if this list contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied LinkedList this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { return indexOf(o) >= 0; } @@ -356,6 +361,7 @@ public boolean contains(@GuardSatisfied LinkedList this, @GuardSatisfied @Nul * @return {@code true} (as specified by {@link Collection#add}) */ @ReleasesNoLocks + @EnsuresNonEmpty("this") public boolean add(@GuardSatisfied LinkedList this, E e) { linkLast(e); return true; @@ -685,7 +691,7 @@ Node node(@NonNegative int index) { * @throws NoSuchElementException if this list is empty * @since 1.5 */ - public E element() { + public E element(@GuardSatisfied @NonEmpty LinkedList this) { return getFirst(); } @@ -707,7 +713,7 @@ public E element() { * @throws NoSuchElementException if this list is empty * @since 1.5 */ - public E remove(@GuardSatisfied LinkedList this) { + public E remove(@GuardSatisfied @NonEmpty LinkedList this) { return removeFirst(); } @@ -823,7 +829,7 @@ public void push(@GuardSatisfied LinkedList this, E e) { * @throws NoSuchElementException if this list is empty * @since 1.6 */ - public E pop(@GuardSatisfied LinkedList this) { + public E pop(@GuardSatisfied @NonEmpty LinkedList this) { return removeFirst(); } @@ -906,11 +912,12 @@ private class ListItr implements ListIterator { nextIndex = index; } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return nextIndex < size; } - public E next() { + public E next(@NonEmpty ListItr this) { checkForComodification(); if (!hasNext()) throw new NoSuchElementException(); @@ -1017,10 +1024,11 @@ public Iterator descendingIterator() { */ private class DescendingIterator implements Iterator { private final ListItr itr = new ListItr(size()); + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return itr.hasPrevious(); } - public E next() { + public E next(@NonEmpty DescendingIterator this) { return itr.previous(); } public void remove() { diff --git a/src/java.base/share/classes/java/util/List.java b/src/java.base/share/classes/java/util/List.java index b91f3d519ec..31e2f761049 100644 --- a/src/java.base/share/classes/java/util/List.java +++ b/src/java.base/share/classes/java/util/List.java @@ -31,6 +31,10 @@ import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.lock.qual.ReleasesNoLocks; +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.nullness.qual.PolyNull; import org.checkerframework.checker.signedness.qual.PolySigned; @@ -175,6 +179,7 @@ public interface List extends Collection { * @return {@code true} if this list contains no elements */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") boolean isEmpty(@GuardSatisfied List this); /** @@ -193,6 +198,7 @@ public interface List extends Collection { * (optional) */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") boolean contains(@GuardSatisfied List this, @UnknownSignedness Object o); /** @@ -201,7 +207,7 @@ public interface List extends Collection { * @return an iterator over the elements in this list in proper sequence */ @SideEffectFree - Iterator iterator(); + @PolyNonEmpty Iterator iterator(@PolyNonEmpty List this); /** * Returns an array containing all of the elements in this list in proper @@ -290,6 +296,7 @@ public interface List extends Collection { * prevents it from being added to this list */ @ReleasesNoLocks + @EnsuresNonEmpty("this") boolean add(@GuardSatisfied List this, E e); /** @@ -360,6 +367,7 @@ public interface List extends Collection { * specified collection prevents it from being added to this list * @see #add(Object) */ + @EnsuresNonEmptyIf(result = true, expression = "this") boolean addAll(@GuardSatisfied List this, Collection c); /** @@ -389,6 +397,7 @@ public interface List extends Collection { * @throws IndexOutOfBoundsException if the index is out of range * ({@code index < 0 || index > size()}) */ + @EnsuresNonEmptyIf(result = true, expression = "this") boolean addAll(@GuardSatisfied List this, @IndexOrHigh({"this"}) int index, Collection c); /** @@ -842,7 +851,7 @@ static List of() { * * @since 9 */ - static List of(E e1) { + static @NonEmpty List of(E e1) { return new ImmutableCollections.List12<>(e1); } @@ -859,7 +868,7 @@ static List of(E e1) { * * @since 9 */ - static List of(E e1, E e2) { + static @NonEmpty List of(E e1, E e2) { return new ImmutableCollections.List12<>(e1, e2); } @@ -877,7 +886,7 @@ static List of(E e1, E e2) { * * @since 9 */ - static List of(E e1, E e2, E e3) { + static @NonEmpty List of(E e1, E e2, E e3) { return ImmutableCollections.listFromTrustedArray(e1, e2, e3); } @@ -896,7 +905,7 @@ static List of(E e1, E e2, E e3) { * * @since 9 */ - static List of(E e1, E e2, E e3, E e4) { + static @NonEmpty List of(E e1, E e2, E e3, E e4) { return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4); } @@ -916,7 +925,7 @@ static List of(E e1, E e2, E e3, E e4) { * * @since 9 */ - static List of(E e1, E e2, E e3, E e4, E e5) { + static @NonEmpty List of(E e1, E e2, E e3, E e4, E e5) { return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5); } @@ -937,7 +946,7 @@ static List of(E e1, E e2, E e3, E e4, E e5) { * * @since 9 */ - static List of(E e1, E e2, E e3, E e4, E e5, E e6) { + static @NonEmpty List of(E e1, E e2, E e3, E e4, E e5, E e6) { return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5, e6); } @@ -960,7 +969,7 @@ static List of(E e1, E e2, E e3, E e4, E e5, E e6) { * * @since 9 */ - static List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) { + static @NonEmpty List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) { return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5, e6, e7); } @@ -984,7 +993,7 @@ static List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) { * * @since 9 */ - static List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { + static @NonEmpty List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5, e6, e7, e8); } @@ -1009,7 +1018,7 @@ static List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E * * @since 9 */ - static List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) { + static @NonEmpty List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) { return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5, e6, e7, e8, e9); } @@ -1035,7 +1044,7 @@ static List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E * * @since 9 */ - static List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) { + static @NonEmpty List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) { return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10); } @@ -1067,7 +1076,7 @@ static List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E */ @SafeVarargs @SuppressWarnings("varargs") - static List of(E... elements) { + static @PolyNonEmpty List of(E @PolyNonEmpty... elements) { switch (elements.length) { // implicit null check of elements case 0: @SuppressWarnings("unchecked") @@ -1098,7 +1107,7 @@ static List of(E... elements) { * @throws NullPointerException if coll is null, or if it contains any nulls * @since 10 */ - static List copyOf(Collection coll) { + static @PolyNonEmpty List copyOf(@PolyNonEmpty Collection coll) { return ImmutableCollections.listCopy(coll); } } diff --git a/src/java.base/share/classes/java/util/ListIterator.java b/src/java.base/share/classes/java/util/ListIterator.java index 83be41a8937..3d53f610169 100644 --- a/src/java.base/share/classes/java/util/ListIterator.java +++ b/src/java.base/share/classes/java/util/ListIterator.java @@ -28,6 +28,8 @@ import org.checkerframework.checker.index.qual.GTENegativeOne; import org.checkerframework.checker.index.qual.NonNegative; 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.framework.qual.AnnotatedFor; @@ -77,6 +79,7 @@ public interface ListIterator extends Iterator { * traversing the list in the forward direction */ @Pure // @Pure is not necessary here: it's inherited from Iterator + @EnsuresNonEmptyIf(result = true, expression = "this") boolean hasNext(); /** @@ -89,7 +92,7 @@ public interface ListIterator extends Iterator { * @return the next element in the list * @throws NoSuchElementException if the iteration has no next element */ - E next(@GuardSatisfied ListIterator this); + E next(@GuardSatisfied @NonEmpty ListIterator this); /** * Returns {@code true} if this list iterator has more elements when diff --git a/src/java.base/share/classes/java/util/Map.java b/src/java.base/share/classes/java/util/Map.java index 1fe509c010b..225046c738a 100644 --- a/src/java.base/share/classes/java/util/Map.java +++ b/src/java.base/share/classes/java/util/Map.java @@ -28,6 +28,10 @@ import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.lock.qual.ReleasesNoLocks; +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.EnsuresKeyFor; import org.checkerframework.checker.nullness.qual.EnsuresKeyForIf; import org.checkerframework.checker.nullness.qual.KeyFor; @@ -176,7 +180,7 @@ * @since 1.2 */ @CFComment({"lock/nullness: Subclasses of this interface/class may opt to prohibit null elements"}) -@AnnotatedFor({"lock", "nullness", "index", "aliasing"}) +@AnnotatedFor({"lock", "nullness", "index", "aliasing", "nonempty"}) public interface Map { // Query Operations @@ -196,6 +200,7 @@ public interface Map { * @return {@code true} if this map contains no key-value mappings */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") boolean isEmpty(@GuardSatisfied Map this); /** @@ -217,6 +222,7 @@ public interface Map { */ @CFComment("nullness: key is not @Nullable because this map might not permit null values") @EnsuresKeyForIf(expression={"#1"}, result=true, map={"this"}) + @EnsuresNonEmptyIf(result=true, expression={"this"}) @Pure boolean containsKey(@GuardSatisfied Map this, @GuardSatisfied @UnknownSignedness Object key); @@ -238,6 +244,7 @@ public interface Map { * map does not permit null values * (optional) */ + @EnsuresNonEmptyIf(result=true, expression={"this"}) @Pure boolean containsValue(@GuardSatisfied Map this, @GuardSatisfied @UnknownSignedness Object value); @@ -298,6 +305,7 @@ public interface Map { */ @ReleasesNoLocks @EnsuresKeyFor(value={"#1"}, map={"this"}) + @EnsuresNonEmpty("this") @Nullable V put(@GuardSatisfied Map this, K key, V value); /** @@ -385,7 +393,7 @@ public interface Map { * @return a set view of the keys contained in this map */ @SideEffectFree - Set<@KeyFor({"this"}) K> keySet(@GuardSatisfied Map this); + @PolyNonEmpty Set<@KeyFor({"this"}) K> keySet(@GuardSatisfied @PolyNonEmpty Map this); /** * Returns a {@link Collection} view of the values contained in this map. @@ -403,7 +411,7 @@ public interface Map { * @return a collection view of the values contained in this map */ @SideEffectFree - Collection values(@GuardSatisfied Map this); + @PolyNonEmpty Collection values(@GuardSatisfied @PolyNonEmpty Map this); /** * Returns a {@link Set} view of the mappings contained in this map. @@ -422,7 +430,7 @@ public interface Map { * @return a set view of the mappings contained in this map */ @SideEffectFree - Set> entrySet(@GuardSatisfied Map this); + @PolyNonEmpty Set> entrySet(@GuardSatisfied @PolyNonEmpty Map this); /** * A map entry (key-value pair). The Entry may be unmodifiable, or the @@ -1397,7 +1405,7 @@ static Map of() { * * @since 9 */ - static Map of(K k1, V v1) { + static @NonEmpty Map of(K k1, V v1) { return new ImmutableCollections.Map1<>(k1, v1); } @@ -1417,7 +1425,7 @@ static Map of() { * * @since 9 */ - static Map of(K k1, V v1, K k2, V v2) { + static @NonEmpty Map of(K k1, V v1, K k2, V v2) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2); } @@ -1439,7 +1447,7 @@ static Map of() { * * @since 9 */ - static Map of(K k1, V v1, K k2, V v2, K k3, V v3) { + static @NonEmpty Map of(K k1, V v1, K k2, V v2, K k3, V v3) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3); } @@ -1463,7 +1471,7 @@ static Map of() { * * @since 9 */ - static Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { + static @NonEmpty Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4); } @@ -1489,7 +1497,7 @@ static Map of() { * * @since 9 */ - static Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { + static @NonEmpty Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5); } @@ -1517,7 +1525,7 @@ static Map of() { * * @since 9 */ - static Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, + static @NonEmpty Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6); @@ -1549,7 +1557,7 @@ static Map of() { * * @since 9 */ - static Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, + static @NonEmpty Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7); @@ -1583,7 +1591,7 @@ static Map of() { * * @since 9 */ - static Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, + static @NonEmpty Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8); @@ -1619,7 +1627,7 @@ static Map of() { * * @since 9 */ - static Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, + static @NonEmpty Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9); @@ -1657,7 +1665,7 @@ static Map of() { * * @since 9 */ - static Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, + static @NonEmpty Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10); @@ -1696,7 +1704,7 @@ static Map of() { */ @SafeVarargs @SuppressWarnings("varargs") - static Map ofEntries(Entry... entries) { + static @PolyNonEmpty Map ofEntries(Entry @PolyNonEmpty... entries) { if (entries.length == 0) { // implicit null check of entries array @SuppressWarnings("unchecked") var map = (Map) ImmutableCollections.EMPTY_MAP; @@ -1775,7 +1783,7 @@ static Map of() { * @since 10 */ @SuppressWarnings({"rawtypes","unchecked"}) - static Map copyOf(Map map) { + static @PolyNonEmpty Map copyOf(@PolyNonEmpty Map map) { if (map instanceof ImmutableCollections.AbstractImmutableMap) { return (Map)map; } else { diff --git a/src/java.base/share/classes/java/util/PrimitiveIterator.java b/src/java.base/share/classes/java/util/PrimitiveIterator.java index bf96fd1b2a8..f0ecc0405cd 100644 --- a/src/java.base/share/classes/java/util/PrimitiveIterator.java +++ b/src/java.base/share/classes/java/util/PrimitiveIterator.java @@ -25,6 +25,7 @@ package java.util; import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.framework.qual.AnnotatedFor; import java.util.function.Consumer; @@ -103,7 +104,7 @@ public static interface OfInt extends PrimitiveIterator { * @return the next {@code int} element in the iteration * @throws NoSuchElementException if the iteration has no more elements */ - int nextInt(); + int nextInt(@NonEmpty OfInt this); /** * {@inheritDoc} @@ -170,7 +171,7 @@ public static interface OfLong extends PrimitiveIterator { * @return the next {@code long} element in the iteration * @throws NoSuchElementException if the iteration has no more elements */ - long nextLong(); + long nextLong(@NonEmpty OfLong this); /** * {@inheritDoc} @@ -236,7 +237,7 @@ public static interface OfDouble extends PrimitiveIterator c) { + public @PolyNonEmpty PriorityQueue(@PolyNonEmpty Collection c) { if (c instanceof SortedSet) { SortedSet ss = (SortedSet) c; this.comparator = (Comparator) ss.comparator(); @@ -322,6 +326,7 @@ private void grow(int minCapacity) { * according to the priority queue's ordering * @throws NullPointerException if the specified element is null */ + @EnsuresNonEmpty("this") public boolean add(@GuardSatisfied PriorityQueue this, E e) { return offer(e); } @@ -406,6 +411,7 @@ void removeEq(Object o) { * @return {@code true} if this queue contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied PriorityQueue this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { return indexOf(o) >= 0; } @@ -529,12 +535,13 @@ private final class Itr implements Iterator { Itr() {} // prevent access constructor creation + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor < size || (forgetMeNot != null && !forgetMeNot.isEmpty()); } - public E next() { + public E next(@NonEmpty Itr this) { if (expectedModCount != modCount) throw new ConcurrentModificationException(); if (cursor < size) diff --git a/src/java.base/share/classes/java/util/Properties.java b/src/java.base/share/classes/java/util/Properties.java index 55d2cea89df..0e4c1914117 100644 --- a/src/java.base/share/classes/java/util/Properties.java +++ b/src/java.base/share/classes/java/util/Properties.java @@ -26,6 +26,7 @@ package java.util; import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nullness.qual.KeyFor; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -1275,6 +1276,7 @@ public int size() { @Override @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return map.isEmpty(); } @@ -1293,6 +1295,7 @@ public Enumeration elements() { @Override @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied @Nullable @UnknownSignedness Object value) { return map.contains(value); } @@ -1368,8 +1371,12 @@ private EntrySet(Set> entrySet) { } @Pure @Override public int size() { return entrySet.size(); } - @Pure @Override public boolean isEmpty() { return entrySet.isEmpty(); } - @Pure @Override public boolean contains(@UnknownSignedness Object o) { return entrySet.contains(o); } + @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") + @Override public boolean isEmpty() { return entrySet.isEmpty(); } + @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") + @Override public boolean contains(@UnknownSignedness Object o) { return entrySet.contains(o); } @Override public Object[] toArray() { return entrySet.toArray(); } @Override public @Nullable T[] toArray(@PolyNull T[] a) { return entrySet.toArray(a); } @Override public void clear() { entrySet.clear(); } diff --git a/src/java.base/share/classes/java/util/Queue.java b/src/java.base/share/classes/java/util/Queue.java index cf85dc5b222..0c7343acc26 100644 --- a/src/java.base/share/classes/java/util/Queue.java +++ b/src/java.base/share/classes/java/util/Queue.java @@ -36,6 +36,9 @@ package java.util; 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.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.framework.qual.AnnotatedFor; @@ -161,6 +164,7 @@ public interface Queue extends Collection { * @throws IllegalArgumentException if some property of this element * prevents it from being added to this queue */ + @EnsuresNonEmpty("this") boolean add(@GuardSatisfied Queue this, E e); /** @@ -190,7 +194,7 @@ public interface Queue extends Collection { * @return the head of this queue * @throws NoSuchElementException if this queue is empty */ - E remove(@GuardSatisfied Queue this); + E remove(@GuardSatisfied @NonEmpty Queue this); /** * Retrieves and removes the head of this queue, @@ -208,7 +212,7 @@ public interface Queue extends Collection { * @return the head of this queue * @throws NoSuchElementException if this queue is empty */ - E element(); + E element(@GuardSatisfied @NonEmpty Queue this); /** * Retrieves, but does not remove, the head of this queue, @@ -221,5 +225,6 @@ public interface Queue extends Collection { @CFComment("Copied from Collection to make it annotatable") @Pure // @EnsuresNonNullIf(expression={"poll()", "peek()"}, result=true) + @EnsuresNonEmptyIf(result = false, expression = "this") boolean isEmpty(@GuardSatisfied Queue this); } diff --git a/src/java.base/share/classes/java/util/RegularEnumSet.java b/src/java.base/share/classes/java/util/RegularEnumSet.java index e3c037e37e0..51ac8675a9a 100644 --- a/src/java.base/share/classes/java/util/RegularEnumSet.java +++ b/src/java.base/share/classes/java/util/RegularEnumSet.java @@ -27,6 +27,9 @@ import org.checkerframework.checker.index.qual.NonNegative; 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.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -104,12 +107,13 @@ private class EnumSetIterator> implements Iterator { unseen = elements; } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return unseen != 0; } @SuppressWarnings("unchecked") - public E next() { + public E next(@NonEmpty EnumSetIterator this) { if (unseen == 0) throw new NoSuchElementException(); lastReturned = unseen & -unseen; @@ -141,6 +145,7 @@ public void remove() { * @return {@code true} if this set contains no elements */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return elements == 0; } @@ -152,6 +157,7 @@ public boolean isEmpty() { * @return {@code true} if this set contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied @Nullable @UnknownSignedness Object e) { if (e == null) return false; @@ -172,6 +178,7 @@ public boolean contains(@GuardSatisfied @Nullable @UnknownSignedness Object e) { * * @throws NullPointerException if {@code e} is null */ + @EnsuresNonEmpty("this") public boolean add(E e) { typeCheck(e); diff --git a/src/java.base/share/classes/java/util/Scanner.java b/src/java.base/share/classes/java/util/Scanner.java index 403e97a281c..ef3bc7aa36d 100644 --- a/src/java.base/share/classes/java/util/Scanner.java +++ b/src/java.base/share/classes/java/util/Scanner.java @@ -31,6 +31,8 @@ import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.mustcall.qual.MustCall; import org.checkerframework.checker.mustcall.qual.MustCallAlias; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.signedness.qual.PolySigned; import org.checkerframework.common.returnsreceiver.qual.This; @@ -1450,6 +1452,7 @@ public String toString(@GuardSatisfied Scanner this) { * @throws IllegalStateException if this scanner is closed * @see java.util.Iterator */ + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext(@GuardSatisfied Scanner this) { ensureOpen(); saveState(); @@ -1476,7 +1479,7 @@ public boolean hasNext(@GuardSatisfied Scanner this) { * @throws IllegalStateException if this scanner is closed * @see java.util.Iterator */ - public String next(@GuardSatisfied Scanner this) { + public String next(@GuardSatisfied @NonEmpty Scanner this) { ensureOpen(); clearCaches(); modCount++; @@ -1518,6 +1521,7 @@ public void remove(@GuardSatisfied Scanner this) { * the specified pattern * @throws IllegalStateException if this scanner is closed */ + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext(@GuardSatisfied Scanner this, String pattern) { return hasNext(patternCache.forName(pattern)); } @@ -1536,7 +1540,7 @@ public boolean hasNext(@GuardSatisfied Scanner this, String pattern) { * @throws NoSuchElementException if no such tokens are available * @throws IllegalStateException if this scanner is closed */ - public String next(@GuardSatisfied Scanner this, String pattern) { + public String next(@GuardSatisfied @NonEmpty Scanner this, String pattern) { return next(patternCache.forName(pattern)); } @@ -1551,6 +1555,7 @@ public String next(@GuardSatisfied Scanner this, String pattern) { * the specified pattern * @throws IllegalStateException if this scanner is closed */ + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext(@GuardSatisfied Scanner this, Pattern pattern) { ensureOpen(); if (pattern == null) @@ -1584,7 +1589,7 @@ public boolean hasNext(@GuardSatisfied Scanner this, Pattern pattern) { * @throws NoSuchElementException if no more tokens are available * @throws IllegalStateException if this scanner is closed */ - public String next(@GuardSatisfied Scanner this, Pattern pattern) { + public String next(@GuardSatisfied @NonEmpty Scanner this, Pattern pattern) { ensureOpen(); if (pattern == null) throw new NullPointerException(); @@ -1655,7 +1660,7 @@ public boolean hasNextLine() { * @throws NoSuchElementException if no line was found * @throws IllegalStateException if this scanner is closed */ - public String nextLine(@GuardSatisfied Scanner this) { + public String nextLine(@GuardSatisfied @NonEmpty Scanner this) { modCount++; if (hasNextPattern == linePattern()) return getCachedResult(); @@ -1838,7 +1843,7 @@ public String nextLine(@GuardSatisfied Scanner this) { * @throws NoSuchElementException if the specified pattern is not found * @throws IllegalStateException if this scanner is closed */ - public @This Scanner skip(@GuardSatisfied Scanner this, Pattern pattern) { + public @This Scanner skip(@GuardSatisfied @NonEmpty Scanner this, Pattern pattern) { ensureOpen(); if (pattern == null) throw new NullPointerException(); @@ -1903,7 +1908,7 @@ public boolean hasNextBoolean(@GuardSatisfied Scanner this) { * @throws NoSuchElementException if input is exhausted * @throws IllegalStateException if this scanner is closed */ - public boolean nextBoolean(@GuardSatisfied Scanner this) { + public boolean nextBoolean(@GuardSatisfied @NonEmpty Scanner this) { clearCaches(); return Boolean.parseBoolean(next(boolPattern())); } @@ -1967,7 +1972,7 @@ public boolean hasNextByte(@GuardSatisfied Scanner this, @Positive @IntRange(fro * @throws NoSuchElementException if input is exhausted * @throws IllegalStateException if this scanner is closed */ - public @PolySigned byte nextByte(@GuardSatisfied Scanner this) { + public @PolySigned byte nextByte(@GuardSatisfied @NonEmpty Scanner this) { return nextByte(defaultRadix); } @@ -2002,7 +2007,7 @@ 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 */ - public @PolySigned byte nextByte(@GuardSatisfied Scanner this, @Positive @IntRange(from = 2, to = 36) int radix) { + 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) && this.radix == radix) { @@ -2083,7 +2088,7 @@ public boolean hasNextShort(@GuardSatisfied Scanner this, @Positive @IntRange(fr * @throws NoSuchElementException if input is exhausted * @throws IllegalStateException if this scanner is closed */ - public @PolySigned short nextShort(@GuardSatisfied Scanner this) { + public @PolySigned short nextShort(@GuardSatisfied @NonEmpty Scanner this) { return nextShort(defaultRadix); } @@ -2118,7 +2123,7 @@ 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 */ - public @PolySigned short nextShort(@GuardSatisfied Scanner this, @Positive @IntRange(from = 2, to = 36) int radix) { + 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) && this.radix == radix) { @@ -2223,7 +2228,7 @@ private String processIntegerToken(String token) { * @throws NoSuchElementException if input is exhausted * @throws IllegalStateException if this scanner is closed */ - public @PolySigned int nextInt(@GuardSatisfied Scanner this) { + public @PolySigned int nextInt(@GuardSatisfied @NonEmpty Scanner this) { return nextInt(defaultRadix); } @@ -2258,7 +2263,7 @@ private String processIntegerToken(String token) { * @throws IllegalStateException if this scanner is closed * @throws IllegalArgumentException if the radix is out of range */ - public @PolySigned int nextInt(@GuardSatisfied Scanner this, @Positive @IntRange(from = 2, to = 36) int radix) { + 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) && this.radix == radix) { @@ -2339,7 +2344,7 @@ public boolean hasNextLong(@GuardSatisfied Scanner this, @Positive @IntRange(fro * @throws NoSuchElementException if input is exhausted * @throws IllegalStateException if this scanner is closed */ - public @PolySigned long nextLong(@GuardSatisfied Scanner this) { + public @PolySigned long nextLong(@GuardSatisfied @NonEmpty Scanner this) { return nextLong(defaultRadix); } @@ -2374,7 +2379,7 @@ 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 */ - public @PolySigned long nextLong(@GuardSatisfied Scanner this, @Positive @IntRange(from = 2, to = 36) int radix) { + 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) && this.radix == radix) { @@ -2498,7 +2503,7 @@ public boolean hasNextFloat(@GuardSatisfied Scanner this) { * @throws NoSuchElementException if input is exhausted * @throws IllegalStateException if this scanner is closed */ - public float nextFloat(@GuardSatisfied Scanner this) { + public float nextFloat(@GuardSatisfied @NonEmpty Scanner this) { // Check cached result if ((typeCache != null) && (typeCache instanceof Float)) { float val = ((Float)typeCache).floatValue(); @@ -2565,7 +2570,7 @@ public boolean hasNextDouble(@GuardSatisfied Scanner this) { * @throws NoSuchElementException if the input is exhausted * @throws IllegalStateException if this scanner is closed */ - public double nextDouble(@GuardSatisfied Scanner this) { + public double nextDouble(@GuardSatisfied @NonEmpty Scanner this) { // Check cached result if ((typeCache != null) && (typeCache instanceof Double)) { double val = ((Double)typeCache).doubleValue(); @@ -2647,7 +2652,7 @@ public boolean hasNextBigInteger(@GuardSatisfied Scanner this, @IntRange(from = * @throws NoSuchElementException if the input is exhausted * @throws IllegalStateException if this scanner is closed */ - public BigInteger nextBigInteger(@GuardSatisfied Scanner this) { + public BigInteger nextBigInteger(@GuardSatisfied @NonEmpty Scanner this) { return nextBigInteger(defaultRadix); } @@ -2677,7 +2682,7 @@ public BigInteger nextBigInteger(@GuardSatisfied Scanner this) { * @throws IllegalStateException if this scanner is closed * @throws IllegalArgumentException if the radix is out of range */ - public BigInteger nextBigInteger(@GuardSatisfied Scanner this, @IntRange(from = 2, to = 36) int radix) { + public BigInteger nextBigInteger(@GuardSatisfied @NonEmpty Scanner this, @IntRange(from = 2, to = 36) int radix) { // Check cached result if ((typeCache != null) && (typeCache instanceof BigInteger val) && this.radix == radix) { @@ -2742,7 +2747,7 @@ public boolean hasNextBigDecimal(@GuardSatisfied Scanner this) { * @throws NoSuchElementException if the input is exhausted * @throws IllegalStateException if this scanner is closed */ - public BigDecimal nextBigDecimal(@GuardSatisfied Scanner this) { + public BigDecimal nextBigDecimal(@GuardSatisfied @NonEmpty Scanner this) { // Check cached result if ((typeCache != null) && (typeCache instanceof BigDecimal val)) { useTypeCache(); diff --git a/src/java.base/share/classes/java/util/ServiceLoader.java b/src/java.base/share/classes/java/util/ServiceLoader.java index d8d7ce13eb5..9ba91eff06f 100644 --- a/src/java.base/share/classes/java/util/ServiceLoader.java +++ b/src/java.base/share/classes/java/util/ServiceLoader.java @@ -27,6 +27,8 @@ import org.checkerframework.checker.interning.qual.UsesObjectEquals; 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.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -939,6 +941,7 @@ private Iterator providers(ModuleLayer layer) { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { while (nextProvider == null && nextError == null) { // get next provider to load @@ -972,7 +975,7 @@ public boolean hasNext() { } @Override - public Provider next() { + public Provider next(@NonEmpty LayerLookupIterator this) { if (!hasNext()) throw new NoSuchElementException(); @@ -1072,6 +1075,7 @@ private Iterator iteratorFor(ClassLoader loader) { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { while (nextProvider == null && nextError == null) { // get next provider to load @@ -1098,7 +1102,7 @@ public boolean hasNext() { } @Override - public Provider next() { + public Provider next(@NonEmpty ModuleServicesLookupIterator this) { if (!hasNext()) throw new NoSuchElementException(); @@ -1275,6 +1279,7 @@ private Provider nextService() { @SuppressWarnings("removal") @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (acc == null) { return hasNextService(); @@ -1288,7 +1293,7 @@ public boolean hasNext() { @SuppressWarnings("removal") @Override - public Provider next() { + public Provider next(@NonEmpty LazyClassPathLookupIterator this) { if (acc == null) { return nextService(); } else { @@ -1312,11 +1317,12 @@ private Iterator> newLookupIterator() { Iterator> second = new LazyClassPathLookupIterator<>(); return new Iterator>() { @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return (first.hasNext() || second.hasNext()); } @Override - public Provider next() { + public Provider next(/*@NonEmpty Iterator> this*/) { if (first.hasNext()) { return first.next(); } else if (second.hasNext()) { @@ -1394,6 +1400,7 @@ private void checkReloadCount() { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { checkReloadCount(); if (index < instantiatedProviders.size()) @@ -1402,7 +1409,7 @@ public boolean hasNext() { } @Override - public S next() { + public S next(/*@NonEmpty Iterator this*/) { checkReloadCount(); S next; if (index < instantiatedProviders.size()) { diff --git a/src/java.base/share/classes/java/util/Set.java b/src/java.base/share/classes/java/util/Set.java index 273f188439b..3e3dda8e533 100644 --- a/src/java.base/share/classes/java/util/Set.java +++ b/src/java.base/share/classes/java/util/Set.java @@ -27,6 +27,10 @@ import org.checkerframework.checker.index.qual.NonNegative; 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.nullness.qual.PolyNull; import org.checkerframework.checker.signedness.qual.PolySigned; @@ -144,6 +148,7 @@ public interface Set extends Collection { * @return {@code true} if this set contains no elements */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") boolean isEmpty(@GuardSatisfied Set this); /** @@ -162,6 +167,7 @@ public interface Set extends Collection { * (optional) */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") boolean contains(@GuardSatisfied Set this, @GuardSatisfied @UnknownSignedness Object o); /** @@ -172,7 +178,7 @@ public interface Set extends Collection { * @return an iterator over the elements in this set */ @SideEffectFree - Iterator iterator(); + @PolyNonEmpty Iterator iterator(@PolyNonEmpty Set this); /** * Returns an array containing all of the elements in this set. @@ -271,6 +277,7 @@ public interface Set extends Collection { * @throws IllegalArgumentException if some property of the specified element * prevents it from being added to this set */ + @EnsuresNonEmpty("this") boolean add(@GuardSatisfied Set this, E e); @@ -344,6 +351,7 @@ public interface Set extends Collection { * specified collection prevents it from being added to this set * @see #add(Object) */ + @EnsuresNonEmptyIf(result = true, expression = "this") boolean addAll(@GuardSatisfied Set this, Collection c); /** @@ -488,7 +496,7 @@ static Set of() { * * @since 9 */ - static Set of(E e1) { + static @NonEmpty Set of(E e1) { return new ImmutableCollections.Set12<>(e1); } @@ -505,7 +513,7 @@ static Set of(E e1) { * * @since 9 */ - static Set of(E e1, E e2) { + static @NonEmpty Set of(E e1, E e2) { return new ImmutableCollections.Set12<>(e1, e2); } @@ -523,7 +531,7 @@ static Set of(E e1, E e2) { * * @since 9 */ - static Set of(E e1, E e2, E e3) { + static @NonEmpty Set of(E e1, E e2, E e3) { return new ImmutableCollections.SetN<>(e1, e2, e3); } @@ -542,7 +550,7 @@ static Set of(E e1, E e2, E e3) { * * @since 9 */ - static Set of(E e1, E e2, E e3, E e4) { + static @NonEmpty Set of(E e1, E e2, E e3, E e4) { return new ImmutableCollections.SetN<>(e1, e2, e3, e4); } @@ -562,7 +570,7 @@ static Set of(E e1, E e2, E e3, E e4) { * * @since 9 */ - static Set of(E e1, E e2, E e3, E e4, E e5) { + static @NonEmpty Set of(E e1, E e2, E e3, E e4, E e5) { return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5); } @@ -583,7 +591,7 @@ static Set of(E e1, E e2, E e3, E e4, E e5) { * * @since 9 */ - static Set of(E e1, E e2, E e3, E e4, E e5, E e6) { + static @NonEmpty Set of(E e1, E e2, E e3, E e4, E e5, E e6) { return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5, e6); } @@ -606,7 +614,7 @@ static Set of(E e1, E e2, E e3, E e4, E e5, E e6) { * * @since 9 */ - static Set of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) { + static @NonEmpty Set of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) { return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5, e6, e7); } @@ -630,7 +638,7 @@ static Set of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) { * * @since 9 */ - static Set of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { + static @NonEmpty Set of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5, e6, e7, e8); } @@ -655,7 +663,7 @@ static Set of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E * * @since 9 */ - static Set of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) { + static @NonEmpty Set of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) { return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5, e6, e7, e8, e9); } @@ -681,7 +689,7 @@ static Set of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E * * @since 9 */ - static Set of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) { + static @NonEmpty Set of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) { return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10); } @@ -747,7 +755,7 @@ static Set of(E... elements) { * @since 10 */ @SuppressWarnings("unchecked") - static Set copyOf(Collection coll) { + static @PolyNonEmpty Set copyOf(@PolyNonEmpty Collection coll) { if (coll instanceof ImmutableCollections.AbstractImmutableSet) { return (Set)coll; } else { diff --git a/src/java.base/share/classes/java/util/SortedMap.java b/src/java.base/share/classes/java/util/SortedMap.java index 56f83f30f71..6a24f696ee3 100644 --- a/src/java.base/share/classes/java/util/SortedMap.java +++ b/src/java.base/share/classes/java/util/SortedMap.java @@ -26,6 +26,7 @@ package java.util; import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.nullness.qual.KeyFor; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.Pure; @@ -228,7 +229,7 @@ public interface SortedMap extends Map { * @throws NoSuchElementException if this map is empty */ @SideEffectFree - @KeyFor("this") K firstKey(@GuardSatisfied SortedMap this); + @KeyFor("this") K firstKey(@GuardSatisfied @NonEmpty SortedMap this); /** * Returns the last (highest) key currently in this map. @@ -237,7 +238,7 @@ public interface SortedMap extends Map { * @throws NoSuchElementException if this map is empty */ @SideEffectFree - @KeyFor("this") K lastKey(@GuardSatisfied SortedMap this); + @KeyFor("this") K lastKey(@GuardSatisfied @NonEmpty SortedMap this); /** * Returns a {@link Set} view of the keys contained in this map. diff --git a/src/java.base/share/classes/java/util/SortedSet.java b/src/java.base/share/classes/java/util/SortedSet.java index 08b07a98c3e..3bdf2739a06 100644 --- a/src/java.base/share/classes/java/util/SortedSet.java +++ b/src/java.base/share/classes/java/util/SortedSet.java @@ -26,6 +26,7 @@ package java.util; import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; @@ -224,7 +225,7 @@ public interface SortedSet extends Set { * @throws NoSuchElementException if this set is empty */ @SideEffectFree - E first(@GuardSatisfied SortedSet this); + E first(@GuardSatisfied @NonEmpty SortedSet this); /** * Returns the last (highest) element currently in this set. @@ -233,7 +234,7 @@ public interface SortedSet extends Set { * @throws NoSuchElementException if this set is empty */ @SideEffectFree - E last(@GuardSatisfied SortedSet this); + E last(@GuardSatisfied @NonEmpty SortedSet this); /** * Creates a {@code Spliterator} over the elements in this sorted set. diff --git a/src/java.base/share/classes/java/util/Spliterators.java b/src/java.base/share/classes/java/util/Spliterators.java index c5a8d1eeb88..405f3ffcc03 100644 --- a/src/java.base/share/classes/java/util/Spliterators.java +++ b/src/java.base/share/classes/java/util/Spliterators.java @@ -24,6 +24,8 @@ */ package java.util; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.dataflow.qual.SideEffectFree; import java.util.function.Consumer; import java.util.function.DoubleConsumer; @@ -683,6 +685,7 @@ public void accept(T t) { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (!valueReady) spliterator.tryAdvance(this); @@ -690,7 +693,7 @@ public boolean hasNext() { } @Override - public T next() { + public T next(@NonEmpty Adapter this) { if (!valueReady && !hasNext()) throw new NoSuchElementException(); else { @@ -742,6 +745,7 @@ public void accept(int t) { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (!valueReady) spliterator.tryAdvance(this); @@ -749,7 +753,7 @@ public boolean hasNext() { } @Override - public int nextInt() { + public int nextInt(@NonEmpty Adapter this) { if (!valueReady && !hasNext()) throw new NoSuchElementException(); else { @@ -797,6 +801,7 @@ public void accept(long t) { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (!valueReady) spliterator.tryAdvance(this); @@ -804,7 +809,7 @@ public boolean hasNext() { } @Override - public long nextLong() { + public long nextLong(@NonEmpty Adapter this) { if (!valueReady && !hasNext()) throw new NoSuchElementException(); else { @@ -852,6 +857,7 @@ public void accept(double t) { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (!valueReady) spliterator.tryAdvance(this); @@ -859,7 +865,7 @@ public boolean hasNext() { } @Override - public double nextDouble() { + public double nextDouble(@NonEmpty Adapter this) { if (!valueReady && !hasNext()) throw new NoSuchElementException(); else { diff --git a/src/java.base/share/classes/java/util/Stack.java b/src/java.base/share/classes/java/util/Stack.java index cfe89024bb3..c3b4dd4a4a2 100644 --- a/src/java.base/share/classes/java/util/Stack.java +++ b/src/java.base/share/classes/java/util/Stack.java @@ -26,6 +26,8 @@ package java.util; import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; @@ -115,7 +117,8 @@ public synchronized E peek() { * @return {@code true} if and only if this stack contains * no items; {@code false} otherwise. */ - @SideEffectFree + @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean empty() { return size() == 0; } diff --git a/src/java.base/share/classes/java/util/StringTokenizer.java b/src/java.base/share/classes/java/util/StringTokenizer.java index fbcf705ffba..074fb7fd480 100644 --- a/src/java.base/share/classes/java/util/StringTokenizer.java +++ b/src/java.base/share/classes/java/util/StringTokenizer.java @@ -27,6 +27,8 @@ import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.interning.qual.UsesObjectEquals; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.common.value.qual.MinLen; import org.checkerframework.framework.qual.AnnotatedFor; @@ -319,6 +321,7 @@ private boolean isDelimiter(int codePoint) { * in the string after the current position; {@code false} * otherwise. */ + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasMoreTokens() { /* * Temporarily store this position and use it in the following @@ -336,7 +339,7 @@ public boolean hasMoreTokens() { * @throws NoSuchElementException if there are no more tokens in this * tokenizer's string. */ - public @MinLen(1) String nextToken() { + public @MinLen(1) String nextToken(@NonEmpty StringTokenizer this) { /* * If next position already computed in hasMoreElements() and * delimiters have changed between the computation and this invocation, @@ -372,7 +375,7 @@ public boolean hasMoreTokens() { * tokenizer's string. * @throws NullPointerException if delim is {@code null} */ - public @MinLen(1) String nextToken(String delim) { + public @MinLen(1) String nextToken(@NonEmpty StringTokenizer this, String delim) { delimiters = delim; /* delimiter string specified, so set the appropriate flag. */ @@ -392,6 +395,7 @@ public boolean hasMoreTokens() { * @see java.util.Enumeration * @see java.util.StringTokenizer#hasMoreTokens() */ + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasMoreElements() { return hasMoreTokens(); } @@ -408,7 +412,7 @@ public boolean hasMoreElements() { * @see java.util.Enumeration * @see java.util.StringTokenizer#nextToken() */ - public Object nextElement() { + public Object nextElement(@NonEmpty StringTokenizer this) { return nextToken(); } diff --git a/src/java.base/share/classes/java/util/Timer.java b/src/java.base/share/classes/java/util/Timer.java index 9b8ed9a80c5..a311b4b9192 100644 --- a/src/java.base/share/classes/java/util/Timer.java +++ b/src/java.base/share/classes/java/util/Timer.java @@ -27,6 +27,7 @@ import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.interning.qual.*; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.framework.qual.AnnotatedFor; @@ -672,6 +673,7 @@ void rescheduleMin(long newTime) { * Returns true if the priority queue contains no elements. */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") boolean isEmpty() { return size==0; } diff --git a/src/java.base/share/classes/java/util/TreeMap.java b/src/java.base/share/classes/java/util/TreeMap.java index a528c177b7a..9e305916785 100644 --- a/src/java.base/share/classes/java/util/TreeMap.java +++ b/src/java.base/share/classes/java/util/TreeMap.java @@ -27,9 +27,13 @@ import org.checkerframework.checker.index.qual.NonNegative; 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.EnsuresKeyFor; import org.checkerframework.checker.nullness.qual.EnsuresKeyForIf; import org.checkerframework.checker.nullness.qual.KeyFor; +import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; @@ -196,7 +200,7 @@ public TreeMap(@Nullable Comparator comparator) { * or are not mutually comparable * @throws NullPointerException if the specified map is null */ - public TreeMap(Map m) { + public @PolyNonEmpty TreeMap(@PolyNonEmpty Map m) { comparator = null; putAll(m); } @@ -210,7 +214,7 @@ public TreeMap(Map m) { * and whose comparator is to be used to sort this map * @throws NullPointerException if the specified map is null */ - public TreeMap(SortedMap m) { + public @PolyNonEmpty TreeMap(@PolyNonEmpty SortedMap m) { comparator = m.comparator(); try { buildFromSorted(m.size(), m.entrySet().iterator(), null, null); @@ -306,14 +310,14 @@ public boolean containsValue(@GuardSatisfied TreeMap this, @GuardSatisfied /** * @throws NoSuchElementException {@inheritDoc} */ - public @KeyFor("this") K firstKey() { + public @KeyFor("this") K firstKey(@NonEmpty TreeMap this) { return key(getFirstEntry()); } /** * @throws NoSuchElementException {@inheritDoc} */ - public @KeyFor("this") K lastKey() { + public @KeyFor("this") K lastKey(@NonEmpty TreeMap this) { return key(getLastEntry()); } @@ -1345,6 +1349,7 @@ public Iterator iterator() { } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { return TreeMap.this.containsValue(o); } @@ -1376,6 +1381,7 @@ public Iterator> iterator() { } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { if (!(o instanceof Map.Entry entry)) return false; @@ -1449,8 +1455,10 @@ public Iterator descendingIterator() { @Pure public @NonNegative int size() { return m.size(); } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return m.isEmpty(); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { return m.containsKey(o); } public void clear() { m.clear(); } public E lower(E e) { return m.lowerKey(e); } @@ -1517,6 +1525,7 @@ abstract class PrivateEntryIterator implements Iterator { next = first; } + @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean hasNext() { return next != null; } @@ -1561,7 +1570,7 @@ final class EntryIterator extends PrivateEntryIterator> { EntryIterator(Entry first) { super(first); } - public Map.Entry next() { + public Map.Entry next(@NonEmpty EntryIterator this) { return nextEntry(); } } @@ -1570,7 +1579,7 @@ final class ValueIterator extends PrivateEntryIterator { ValueIterator(Entry first) { super(first); } - public V next() { + public V next(@NonEmpty ValueIterator this) { return nextEntry().value; } } @@ -1579,7 +1588,7 @@ final class KeyIterator extends PrivateEntryIterator { KeyIterator(Entry first) { super(first); } - public K next() { + public K next(@NonEmpty KeyIterator this) { return nextEntry().key; } } @@ -1588,7 +1597,7 @@ final class DescendingKeyIterator extends PrivateEntryIterator { DescendingKeyIterator(Entry first) { super(first); } - public K next() { + public K next(@NonEmpty DescendingKeyIterator this) { return prevEntry().key; } public void remove() { @@ -1640,7 +1649,7 @@ static K keyOrNull(TreeMap.Entry e) { * Returns the key corresponding to the specified Entry. * @throws NoSuchElementException if the Entry is null */ - static K key(Entry e) { + static K key(@NonNull Entry e) { if (e==null) throw new NoSuchElementException(); return e.key; @@ -1822,6 +1831,7 @@ final TreeMap.Entry absLowFence() { // public methods @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return (fromStart && toEnd) ? m.isEmpty() : entrySet().isEmpty(); } @@ -2010,12 +2020,14 @@ public int size() { } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { TreeMap.Entry n = absLowest(); return n == null || tooHigh(n.key); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { if (!(o instanceof Entry entry)) return false; @@ -2060,6 +2072,7 @@ abstract class SubMapIterator implements Iterator { fenceKey = fence == null ? UNBOUNDED : fence.key; } + @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean hasNext() { return next != null && next.key != fenceKey; } @@ -2116,7 +2129,7 @@ final class SubMapEntryIterator extends SubMapIterator> { TreeMap.Entry fence) { super(first, fence); } - public Map.Entry next() { + public Map.Entry next(@NonEmpty SubMapEntryIterator this) { return nextEntry(); } public void remove() { @@ -2130,7 +2143,7 @@ final class DescendingSubMapEntryIterator extends SubMapIterator> super(last, fence); } - public Map.Entry next() { + public Map.Entry next(@NonEmpty DescendingSubMapEntryIterator this) { return prevEntry(); } public void remove() { @@ -2145,7 +2158,7 @@ final class SubMapKeyIterator extends SubMapIterator TreeMap.Entry fence) { super(first, fence); } - public K next() { + public K next(@NonEmpty SubMapKeyIterator this) { return nextEntry().key; } public void remove() { @@ -2183,7 +2196,7 @@ final class DescendingSubMapKeyIterator extends SubMapIterator TreeMap.Entry fence) { super(last, fence); } - public K next() { + public K next(@NonEmpty DescendingSubMapKeyIterator this) { return prevEntry().key; } public void remove() { diff --git a/src/java.base/share/classes/java/util/TreeSet.java b/src/java.base/share/classes/java/util/TreeSet.java index f6e5d8e8fb3..1763fbf81de 100644 --- a/src/java.base/share/classes/java/util/TreeSet.java +++ b/src/java.base/share/classes/java/util/TreeSet.java @@ -27,6 +27,10 @@ import org.checkerframework.checker.index.qual.NonNegative; 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.Nullable; import org.checkerframework.checker.signedness.qual.UnknownSignedness; @@ -167,7 +171,7 @@ public TreeSet(@Nullable Comparator comparator) { * not {@link Comparable}, or are not mutually comparable * @throws NullPointerException if the specified collection is null */ - public TreeSet(Collection c) { + public @PolyNonEmpty TreeSet(@PolyNonEmpty Collection c) { this(); addAll(c); } @@ -179,7 +183,7 @@ public TreeSet(Collection c) { * @param s sorted set whose elements will comprise the new set * @throws NullPointerException if the specified sorted set is null */ - public TreeSet(SortedSet s) { + public @PolyNonEmpty TreeSet(@PolyNonEmpty SortedSet s) { this(s.comparator()); addAll(s); } @@ -190,7 +194,7 @@ public TreeSet(SortedSet s) { * @return an iterator over the elements in this set in ascending order */ @SideEffectFree - public Iterator iterator() { + public @PolyNonEmpty Iterator iterator(@PolyNonEmpty TreeSet this) { return m.navigableKeySet().iterator(); } @@ -200,7 +204,7 @@ public Iterator iterator() { * @return an iterator over the elements in this set in descending order * @since 1.6 */ - public Iterator descendingIterator() { + public @PolyNonEmpty Iterator descendingIterator(@PolyNonEmpty TreeSet this) { return m.descendingKeySet().iterator(); } @@ -228,6 +232,7 @@ public NavigableSet descendingSet() { */ @EnsuresNonNullIf(expression={"pollFirst()", "pollLast()"}, result=false) @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty(@GuardSatisfied TreeSet this) { return m.isEmpty(); } @@ -247,6 +252,7 @@ public boolean isEmpty(@GuardSatisfied TreeSet this) { * does not permit null elements */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied TreeSet this, @GuardSatisfied @UnknownSignedness Object o) { return m.containsKey(o); } @@ -268,6 +274,7 @@ public boolean contains(@GuardSatisfied TreeSet this, @GuardSatisfied @Unknow * and this set uses natural ordering, or its comparator * does not permit null elements */ + @EnsuresNonEmpty("this") public boolean add(@GuardSatisfied TreeSet this, E e) { return m.put(e, PRESENT)==null; } @@ -412,7 +419,7 @@ public SortedSet tailSet(@GuardSatisfied TreeSet this, E fromElement) { * @throws NoSuchElementException {@inheritDoc} */ @SideEffectFree - public E first(@GuardSatisfied TreeSet this) { + public E first(@GuardSatisfied @NonEmpty TreeSet this) { return m.firstKey(); } @@ -420,7 +427,7 @@ public E first(@GuardSatisfied TreeSet this) { * @throws NoSuchElementException {@inheritDoc} */ @SideEffectFree - public E last(@GuardSatisfied TreeSet this) { + public E last(@GuardSatisfied @NonEmpty TreeSet this) { return m.lastKey(); } diff --git a/src/java.base/share/classes/java/util/Vector.java b/src/java.base/share/classes/java/util/Vector.java index 869ea5dd463..91fba253f06 100644 --- a/src/java.base/share/classes/java/util/Vector.java +++ b/src/java.base/share/classes/java/util/Vector.java @@ -28,6 +28,10 @@ import org.checkerframework.checker.index.qual.GTENegativeOne; import org.checkerframework.checker.index.qual.NonNegative; 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.nullness.qual.PolyNull; import org.checkerframework.checker.signedness.qual.PolySigned; @@ -192,7 +196,7 @@ public Vector() { * @throws NullPointerException if the specified collection is null * @since 1.2 */ - public Vector(Collection c) { + public @PolyNonEmpty Vector(@PolyNonEmpty Collection c) { Object[] a = c.toArray(); elementCount = a.length; if (c.getClass() == ArrayList.class) { @@ -328,6 +332,7 @@ public synchronized void setSize(@GuardSatisfied Vector this, @NonNegative in * {@code false} otherwise. */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public synchronized boolean isEmpty(@GuardSatisfied Vector this) { return elementCount == 0; } @@ -347,11 +352,12 @@ public Enumeration elements() { return new Enumeration() { int count = 0; + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasMoreElements() { return count < elementCount; } - public E nextElement() { + public E nextElement(/*@NonEmpty Enumeration this*/) { synchronized (Vector.this) { if (count < elementCount) { return elementData(count++); @@ -372,6 +378,7 @@ public E nextElement() { * @return {@code true} if this vector contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied Vector this, @GuardSatisfied @Nullable @UnknownSignedness Object o) { return indexOf(o, 0) >= 0; } @@ -497,7 +504,7 @@ public synchronized E elementAt(@NonNegative int index) { * @return the first component of this vector * @throws NoSuchElementException if this vector has no components */ - public synchronized E firstElement() { + public synchronized E firstElement(@NonEmpty Vector this) { if (elementCount == 0) { throw new NoSuchElementException(); } @@ -511,7 +518,7 @@ public synchronized E firstElement() { * {@code size() - 1} * @throws NoSuchElementException if this vector is empty */ - public synchronized E lastElement() { + public synchronized E lastElement(@NonEmpty Vector this) { if (elementCount == 0) { throw new NoSuchElementException(); } @@ -816,6 +823,7 @@ private void add(E e, Object[] elementData, int s) { * @return {@code true} (as specified by {@link Collection#add}) * @since 1.2 */ + @EnsuresNonEmpty("this") public synchronized boolean add(@GuardSatisfied Vector this, E e) { modCount++; add(e, elementData, elementCount); @@ -1269,13 +1277,14 @@ private class Itr implements Iterator { int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { // Racy but within spec, since modifications are checked // within or after synchronization in next/previous return cursor != elementCount; } - public E next() { + public E next(@NonEmpty Itr this) { synchronized (Vector.this) { checkForComodification(); int i = cursor; diff --git a/src/java.base/share/classes/java/util/WeakHashMap.java b/src/java.base/share/classes/java/util/WeakHashMap.java index 1e452660baf..82257b2a891 100644 --- a/src/java.base/share/classes/java/util/WeakHashMap.java +++ b/src/java.base/share/classes/java/util/WeakHashMap.java @@ -27,6 +27,9 @@ import org.checkerframework.checker.index.qual.NonNegative; 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.EnsuresKeyFor; import org.checkerframework.checker.nullness.qual.EnsuresKeyForIf; import org.checkerframework.checker.nullness.qual.KeyFor; @@ -265,7 +268,7 @@ public WeakHashMap() { * @throws NullPointerException if the specified map is null * @since 1.3 */ - public WeakHashMap(Map m) { + public @PolyNonEmpty WeakHashMap(@PolyNonEmpty Map m) { this(Math.max((int) ((float)m.size() / DEFAULT_LOAD_FACTOR + 1.0F), DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); @@ -392,6 +395,7 @@ private Entry[] getTable() { * because they are no longer referenced. */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty(@GuardSatisfied WeakHashMap this) { return size() == 0; } @@ -804,6 +808,7 @@ private abstract class HashIterator implements Iterator { index = isEmpty() ? 0 : table.length; } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { Entry[] t = table; @@ -854,19 +859,19 @@ public void remove() { } private class ValueIterator extends HashIterator { - public V next() { + public V next(@NonEmpty ValueIterator this) { return nextEntry().value; } } private class KeyIterator extends HashIterator { - public K next() { + public K next(@NonEmpty KeyIterator this) { return nextEntry().getKey(); } } private class EntryIterator extends HashIterator> { - public Map.Entry next() { + public Map.Entry next(@NonEmpty EntryIterator this) { return nextEntry(); } } @@ -910,6 +915,7 @@ public Iterator iterator() { } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@Nullable @UnknownSignedness Object o) { return containsKey(o); } @@ -968,6 +974,7 @@ public Iterator iterator() { } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@Nullable @UnknownSignedness Object o) { return containsValue(o); } @@ -1009,6 +1016,7 @@ public Iterator> iterator() { } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@Nullable @UnknownSignedness Object o) { return o instanceof Map.Entry e && getEntry(e.getKey()) != null 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 6a57342bf63..7139660c9fc 100644 --- a/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java @@ -36,6 +36,9 @@ package java.util.concurrent; 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.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -335,6 +338,7 @@ public ArrayBlockingQueue(int capacity, boolean fair, * @throws IllegalStateException if this queue is full * @throws NullPointerException if the specified element is null */ + @EnsuresNonEmpty("this") public boolean add(E e) { return super.add(e); } @@ -551,6 +555,7 @@ public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { * @return {@code true} if this queue contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o == null) return false; final ReentrantLock lock = this.lock; @@ -1192,6 +1197,7 @@ private void detach() { * fields (i.e. nextItem) that are not modified by update operations * triggered by queue modifications. */ + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (nextItem != null) return true; @@ -1221,7 +1227,7 @@ private void noNext() { } } - public E next() { + public E next(@NonEmpty Itr this) { final E e = nextItem; if (e == null) throw new NoSuchElementException(); 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 9b156b687b8..2180e76e280 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,12 @@ package java.util.concurrent; -import org.checkerframework.checker.signedness.qual.UnknownSignedness; +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.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -452,6 +455,7 @@ boolean offerLast(E e, long timeout, TimeUnit unit) * @throws IllegalArgumentException if some property of the specified * element prevents it from being added to this deque */ + @EnsuresNonEmpty("this") boolean add(E e); /** @@ -523,7 +527,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(); + E remove(@NonEmpty BlockingDeque this); /** * Retrieves and removes the head of the queue represented by this deque @@ -574,7 +578,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * @return the head of this deque * @throws NoSuchElementException if this deque is empty */ - E element(); + E element(@NonEmpty BlockingDeque this); /** * Retrieves, but does not remove, the head of the queue represented by @@ -622,6 +626,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * (optional) */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") boolean contains(@UnknownSignedness Object o); /** 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 1f0cf5b6961..b4e99d9d203 100644 --- a/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java @@ -35,9 +35,12 @@ package java.util.concurrent; -import org.checkerframework.checker.signedness.qual.UnknownSignedness; +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.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.framework.qual.AnnotatedFor; @@ -202,6 +205,7 @@ public interface BlockingQueue extends Queue { * @throws IllegalArgumentException if some property of the specified * element prevents it from being added to this queue */ + @EnsuresNonEmpty("this") boolean add(E e); /** @@ -329,6 +333,7 @@ boolean offer(E e, long timeout, TimeUnit unit) * (optional) */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") boolean contains(@UnknownSignedness Object o); /** 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 3b0bf73be1f..26dbff64f8e 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java @@ -36,6 +36,9 @@ package java.util.concurrent; 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.nullness.qual.EnsuresKeyFor; import org.checkerframework.checker.nullness.qual.EnsuresKeyForIf; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; @@ -933,6 +936,7 @@ public int size() { * {@inheritDoc} */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return sumCount() <= 0L; // ignore transient negative values } @@ -2161,6 +2165,7 @@ else if (f instanceof ReservationNode) * @throws NullPointerException if the specified value is null */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied @UnknownSignedness Object value) { return containsValue(value); } @@ -3486,7 +3491,7 @@ static final class KeyIterator extends BaseIterator super(tab, size, index, limit, map); } - public final K next() { + public final K next(@NonEmpty KeyIterator this) { Node p; if ((p = next) == null) throw new NoSuchElementException(); @@ -3496,7 +3501,7 @@ public final K next() { return k; } - public final K nextElement() { return next(); } + public final K nextElement(@NonEmpty KeyIterator this) { return next(); } } static final class ValueIterator extends BaseIterator @@ -3506,7 +3511,7 @@ static final class ValueIterator extends BaseIterator super(tab, size, index, limit, map); } - public final V next() { + public final V next(@NonEmpty ValueIterator this) { Node p; if ((p = next) == null) throw new NoSuchElementException(); @@ -3516,7 +3521,7 @@ public final V next() { return v; } - public final V nextElement() { return next(); } + public final V nextElement(@NonEmpty ValueIterator this) { return next(); } } static final class EntryIterator extends BaseIterator @@ -3526,7 +3531,7 @@ static final class EntryIterator extends BaseIterator super(tab, size, index, limit, map); } - public final Map.Entry next() { + public final Map.Entry next(@NonEmpty EntryIterator this) { Node p; if ((p = next) == null) throw new NoSuchElementException(); @@ -4469,6 +4474,7 @@ abstract static class CollectionView @Pure public final int size() { return map.size(); } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public final boolean isEmpty() { return map.isEmpty(); } // implementations below rely on concrete classes supplying these @@ -4484,6 +4490,7 @@ abstract static class CollectionView @SideEffectFree public abstract Iterator iterator(); @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public abstract boolean contains(@UnknownSignedness Object o); public abstract boolean remove(@UnknownSignedness Object o); @@ -4652,6 +4659,7 @@ public static class KeySetView extends CollectionView * @throws NullPointerException if the specified key is null */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { return map.containsKey(o); } /** @@ -4686,6 +4694,7 @@ public Iterator iterator() { * @throws UnsupportedOperationException if no default mapped value * for additions was provided */ + @EnsuresNonEmpty("this") public boolean add(K e) { V v; if ((v = value) == null) @@ -4760,6 +4769,7 @@ static final class ValuesView extends CollectionView private static final long serialVersionUID = 2249069246763182397L; ValuesView(ConcurrentHashMap map) { super(map); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean contains(@UnknownSignedness Object o) { return map.containsValue(o); } @@ -4784,6 +4794,7 @@ public final Iterator iterator() { return new ValueIterator(t, f, 0, f, m); } + @EnsuresNonEmpty("this") public final boolean add(V e) { throw new UnsupportedOperationException(); } @@ -4838,6 +4849,7 @@ static final class EntrySetView extends CollectionView> EntrySetView(ConcurrentHashMap map) { super(map); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { Object k, v, r; Map.Entry e; return ((o instanceof Map.Entry) && @@ -4866,6 +4878,7 @@ public Iterator> iterator() { return new EntryIterator(t, f, 0, f, m); } + @EnsuresNonEmpty("this") public boolean add(Entry e) { return map.putVal(e.getKey(), e.getValue(), false) == null; } 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 a06c4879e5c..4cbcdc902d5 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java @@ -36,6 +36,9 @@ package java.util.concurrent; 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.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -771,7 +774,7 @@ else if (p == t * @param v the element * @return the element */ - private E screenNullResult(E v) { + private E screenNullResult(@NonNull E v) { if (v == null) throw new NoSuchElementException(); return v; @@ -911,14 +914,14 @@ public boolean offerLast(E e) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E getFirst() { + public E getFirst(@NonEmpty ConcurrentLinkedDeque this) { return screenNullResult(peekFirst()); } /** * @throws NoSuchElementException {@inheritDoc} */ - public E getLast() { + public E getLast(@NonEmpty ConcurrentLinkedDeque this) { return screenNullResult(peekLast()); } @@ -967,14 +970,14 @@ public E getLast() { /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeFirst() { + public E removeFirst(@NonEmpty ConcurrentLinkedDeque this) { return screenNullResult(pollFirst()); } /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeLast() { + public E removeLast(@NonEmpty ConcurrentLinkedDeque this) { return screenNullResult(pollLast()); } @@ -999,6 +1002,7 @@ public boolean offer(E e) { * @return {@code true} (as specified by {@link Collection#add}) * @throws NullPointerException if the specified element is null */ + @EnsuresNonEmpty("this") public boolean add(E e) { return offerLast(e); } @@ -1009,17 +1013,17 @@ public boolean add(E e) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E remove() { return removeFirst(); } + public E remove(@NonEmpty ConcurrentLinkedDeque this) { return removeFirst(); } /** * @throws NoSuchElementException {@inheritDoc} */ - public E pop() { return removeFirst(); } + public E pop(@NonEmpty ConcurrentLinkedDeque this) { return removeFirst(); } /** * @throws NoSuchElementException {@inheritDoc} */ - public E element() { return getFirst(); } + public E element(@NonEmpty ConcurrentLinkedDeque this) { return getFirst(); } /** * @throws NullPointerException {@inheritDoc} @@ -1087,6 +1091,7 @@ public boolean removeLastOccurrence(Object o) { * @return {@code true} if this deque contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied @UnknownSignedness Object o) { if (o != null) { for (Node p = first(); p != null; p = succ(p)) { @@ -1105,6 +1110,7 @@ public boolean contains(@GuardSatisfied @UnknownSignedness Object o) { */ @EnsuresNonNullIf(expression={"peek()", "peekFirst()", "peekLast()", "poll()", "pollFirst()", "pollLast()"}, result=false) @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return peekFirst() == null; } @@ -1426,11 +1432,12 @@ private void advance() { } } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return nextItem != null; } - public E next() { + public E next(@NonEmpty AbstractItr this) { E item = nextItem; if (item == null) throw new NoSuchElementException(); advance(); 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 c2b28a618d6..e7e1ed12b1e 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java @@ -36,6 +36,9 @@ package java.util.concurrent; 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.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -290,6 +293,7 @@ public ConcurrentLinkedQueue(Collection c) { * @return {@code true} (as specified by {@link Collection#add}) * @throws NullPointerException if the specified element is null */ + @EnsuresNonEmpty("this") public boolean add(E e) { return offer(e); } @@ -455,6 +459,7 @@ else if (p == q) * @return {@code true} if this queue contains no elements */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return first() == null; } @@ -499,6 +504,7 @@ public int size() { * @return {@code true} if this queue contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied @UnknownSignedness Object o) { if (o == null) return false; restartFromHead: for (;;) { @@ -785,11 +791,12 @@ else if (p == q) } } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return nextItem != null; } - public E next() { + public E next(@NonEmpty Itr this) { final Node pred = nextNode; if (pred == null) throw new NoSuchElementException(); // assert nextItem != null; 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 770296e0353..d4de695aa46 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java @@ -36,6 +36,8 @@ package java.util.concurrent; 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.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -1416,6 +1418,7 @@ public int size() { * {@inheritDoc} */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return findFirst() == null; } @@ -1874,7 +1877,7 @@ public Comparator comparator() { /** * @throws NoSuchElementException {@inheritDoc} */ - public K firstKey() { + public K firstKey(@NonEmpty ConcurrentSkipListMap this) { Node n = findFirst(); if (n == null) throw new NoSuchElementException(); @@ -1884,7 +1887,7 @@ public K firstKey() { /** * @throws NoSuchElementException {@inheritDoc} */ - public K lastKey() { + public K lastKey(@NonEmpty ConcurrentSkipListMap this) { Node n = findLast(); if (n == null) throw new NoSuchElementException(); @@ -2117,6 +2120,7 @@ abstract class Iter implements Iterator { advance(baseHead()); } + @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean hasNext() { return next != null; } @@ -2145,7 +2149,7 @@ public final void remove() { } final class ValueIterator extends Iter { - public V next() { + public V next(@NonEmpty ValueIterator this) { V v; if ((v = nextValue) == null) throw new NoSuchElementException(); @@ -2155,7 +2159,7 @@ public V next() { } final class KeyIterator extends Iter { - public K next() { + public K next(@NonEmpty KeyIterator this) { Node n; if ((n = next) == null) throw new NoSuchElementException(); @@ -2166,7 +2170,7 @@ public K next() { } final class EntryIterator extends Iter> { - public Map.Entry next() { + public Map.Entry next(@NonEmpty EntryIterator this) { Node n; if ((n = next) == null) throw new NoSuchElementException(); @@ -2200,8 +2204,10 @@ static final class KeySet @Pure public int size() { return m.size(); } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return m.isEmpty(); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { return m.containsKey(o); } public boolean remove(@UnknownSignedness Object o) { return m.remove(o) != null; } public void clear() { m.clear(); } @@ -2288,8 +2294,10 @@ public Iterator iterator() { @Pure public int size() { return m.size(); } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return m.isEmpty(); } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { return m.containsValue(o); } public void clear() { m.clear(); } public Object[] toArray() { return toList(this).toArray(); } @@ -2331,6 +2339,7 @@ public Iterator> iterator() { } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { if (!(o instanceof Map.Entry)) return false; @@ -2346,6 +2355,7 @@ public boolean remove(@UnknownSignedness Object o) { e.getValue()); } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return m.isEmpty(); } @@ -2518,7 +2528,7 @@ else if (hiInclusive) /** * Returns lowest absolute key (ignoring directionality). */ - K lowestKey() { + K lowestKey(@NonEmpty SubMap this) { Comparator cmp = m.comparator; ConcurrentSkipListMap.Node n = loNode(cmp); if (isBeforeEnd(n, cmp)) @@ -2530,7 +2540,7 @@ K lowestKey() { /** * Returns highest absolute key (ignoring directionality). */ - K highestKey() { + K highestKey(@NonEmpty SubMap this) { Comparator cmp = m.comparator; ConcurrentSkipListMap.Node n = hiNode(cmp); if (n != null) { @@ -2685,6 +2695,7 @@ public int size() { } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { Comparator cmp = m.comparator; return !isBeforeEnd(loNode(cmp), cmp); @@ -2951,11 +2962,12 @@ abstract class SubMapIter implements Iterator, Spliterator { } } + @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean hasNext() { return next != null; } - final void advance() { + final void advance(@NonEmpty SubMapIter this) { if (next == null) throw new NoSuchElementException(); lastReturned = next; @@ -3031,7 +3043,7 @@ public long estimateSize() { } final class SubMapValueIterator extends SubMapIter { - public V next() { + public V next(@NonEmpty SubMapValueIterator this) { V v = nextValue; advance(); return v; @@ -3042,7 +3054,7 @@ public int characteristics() { } final class SubMapKeyIterator extends SubMapIter { - public K next() { + public K next(@NonEmpty SubMapKeyIterator this) { Node n = next; advance(); return n.key; @@ -3057,7 +3069,7 @@ public final Comparator getComparator() { } final class SubMapEntryIterator extends SubMapIter> { - public Map.Entry next() { + public Map.Entry next(@NonEmpty SubMapEntryIterator this) { Node n = next; V v = nextValue; advance(); 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 7a90e3885ef..11038b52fe6 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java @@ -36,6 +36,9 @@ package java.util.concurrent; 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.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -219,6 +222,7 @@ public int size() { * @return {@code true} if this set contains no elements */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return m.isEmpty(); } @@ -235,6 +239,7 @@ public boolean isEmpty() { * @throws NullPointerException if the specified element is null */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied @UnknownSignedness Object o) { return m.containsKey(o); } @@ -253,6 +258,7 @@ public boolean contains(@GuardSatisfied @UnknownSignedness Object o) { * with the elements currently in this set * @throws NullPointerException if the specified element is null */ + @EnsuresNonEmpty("this") public boolean add(E e) { return m.putIfAbsent(e, Boolean.TRUE) == null; } @@ -410,14 +416,14 @@ public E higher(E e) { /** * @throws java.util.NoSuchElementException {@inheritDoc} */ - public E first() { + public E first(@NonEmpty ConcurrentSkipListSet this) { return m.firstKey(); } /** * @throws java.util.NoSuchElementException {@inheritDoc} */ - public E last() { + public E last(@NonEmpty ConcurrentSkipListSet this) { return m.lastKey(); } 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 59a06554032..a08a17903fb 100644 --- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java +++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java @@ -35,6 +35,9 @@ package java.util.concurrent; 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.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -183,6 +186,7 @@ public int size() { * @return {@code true} if this list contains no elements */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return size() == 0; } @@ -239,6 +243,7 @@ private static int lastIndexOfRange(@Nullable Object o, Object[] es, int from, i * @return {@code true} if this list contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied @Nullable @UnknownSignedness Object o) { return indexOf(o) >= 0; } @@ -438,6 +443,7 @@ public E set(int index, E element) { * @param e element to be appended to this list * @return {@code true} (as specified by {@link Collection#add}) */ + @EnsuresNonEmpty("this") public boolean add(E e) { synchronized (lock) { Object[] es = getArray(); @@ -1101,6 +1107,7 @@ static final class COWIterator implements ListIterator { snapshot = es; } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor < snapshot.length; } @@ -1110,7 +1117,7 @@ public boolean hasPrevious() { } @SuppressWarnings("unchecked") - public E next() { + public E next(@NonEmpty COWIterator this) { if (! hasNext()) throw new NoSuchElementException(); return (E) snapshot[cursor++]; @@ -1296,6 +1303,7 @@ public int lastIndexOf(Object o) { } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@Nullable @UnknownSignedness Object o) { return indexOf(o) >= 0; } @@ -1317,6 +1325,7 @@ public boolean containsAll(Collection implements ListIterator { it = l.listIterator(index + offset); } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return nextIndex() < size; } - public E next() { + public E next(@NonEmpty COWSubListIterator this) { if (hasNext()) return it.next(); else 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 468386877e5..017289436ca 100644 --- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java +++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java @@ -36,6 +36,9 @@ package java.util.concurrent; 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.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -153,6 +156,7 @@ public int size() { * @return {@code true} if this set contains no elements */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return al.isEmpty(); } @@ -166,6 +170,7 @@ public boolean isEmpty() { * @return {@code true} if this set contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied @Nullable @UnknownSignedness Object o) { return al.contains(o); } @@ -270,6 +275,7 @@ public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { * @return {@code true} if this set did not already contain the specified * element */ + @EnsuresNonEmpty("this") public boolean add(E e) { return al.addIfAbsent(e); } 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 1c44a1f7a00..bb81eb21a49 100644 --- a/src/java.base/share/classes/java/util/concurrent/DelayQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/DelayQueue.java @@ -35,6 +35,9 @@ package java.util.concurrent; +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.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -138,6 +141,7 @@ public DelayQueue(Collection c) { * @return {@code true} (as specified by {@link Collection#add}) * @throws NullPointerException if the specified element is null */ + @EnsuresNonEmpty("this") public boolean add(E e) { return offer(e); } @@ -528,12 +532,13 @@ private class Itr implements Iterator { this.array = array; } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor < array.length; } @SuppressWarnings("unchecked") - public E next() { + public E next(@NonEmpty Itr this) { if (cursor >= array.length) throw new NoSuchElementException(); return (E)array[lastRet = cursor++]; diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java index d63b33e8ff8..4e077ada4ae 100644 --- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java @@ -35,6 +35,7 @@ package java.util.concurrent; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.dataflow.qual.Pure; import java.lang.Thread.UncaughtExceptionHandler; @@ -960,6 +961,7 @@ final int queueSize() { * has any tasks than does queueSize. */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") final boolean isEmpty() { return !((source != 0 && owner == null) || top - base > 0); } 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 d665f2d68b2..0b8e7563fa9 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java @@ -36,6 +36,9 @@ package java.util.concurrent; 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.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -451,7 +454,7 @@ public boolean offerLast(E e, long timeout, TimeUnit unit) /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeFirst() { + public E removeFirst(@NonEmpty LinkedBlockingDeque this) { E x = pollFirst(); if (x == null) throw new NoSuchElementException(); return x; @@ -460,7 +463,7 @@ public E removeFirst() { /** * @throws NoSuchElementException {@inheritDoc} */ - public E removeLast() { + public E removeLast(@NonEmpty LinkedBlockingDeque this) { E x = pollLast(); if (x == null) throw new NoSuchElementException(); return x; @@ -551,7 +554,7 @@ public E takeLast() throws InterruptedException { /** * @throws NoSuchElementException {@inheritDoc} */ - public E getFirst() { + public E getFirst(@NonEmpty LinkedBlockingDeque this) { E x = peekFirst(); if (x == null) throw new NoSuchElementException(); return x; @@ -560,7 +563,7 @@ public E getFirst() { /** * @throws NoSuchElementException {@inheritDoc} */ - public E getLast() { + public E getLast(@NonEmpty LinkedBlockingDeque this) { E x = peekLast(); if (x == null) throw new NoSuchElementException(); return x; @@ -632,6 +635,7 @@ public boolean removeLastOccurrence(Object o) { * @throws IllegalStateException if this deque is full * @throws NullPointerException if the specified element is null */ + @EnsuresNonEmpty("this") public boolean add(E e) { addLast(e); return true; @@ -671,7 +675,7 @@ 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() { + public E remove(@NonEmpty LinkedBlockingDeque this) { return removeFirst(); } @@ -697,7 +701,7 @@ public E take() throws InterruptedException { * @return the head of the queue represented by this deque * @throws NoSuchElementException if this deque is empty */ - public E element() { + public E element(@NonEmpty LinkedBlockingDeque this) { return getFirst(); } @@ -775,7 +779,7 @@ public void push(E e) { /** * @throws NoSuchElementException {@inheritDoc} */ - public E pop() { + public E pop(@NonEmpty LinkedBlockingDeque this) { return removeFirst(); } @@ -824,6 +828,7 @@ public int size() { * @return {@code true} if this deque contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o == null) return false; final ReentrantLock lock = this.lock; @@ -1091,11 +1096,12 @@ private Node succ(Node p) { } } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return next != null; } - public E next() { + public E next(@NonEmpty AbstractItr this) { Node p; if ((p = next) == null) throw new NoSuchElementException(); 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 8b31795c04d..916548afc84 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java @@ -36,6 +36,8 @@ package java.util.concurrent; 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.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -572,6 +574,7 @@ public boolean remove(@GuardSatisfied @Nullable @UnknownSignedness Object o) { * @return {@code true} if this queue contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o == null) return false; fullyLock(); @@ -794,11 +797,12 @@ private class Itr implements Iterator { } } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return next != null; } - public E next() { + public E next(@NonEmpty Itr this) { Node p; if ((p = next) == null) throw new NoSuchElementException(); 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 a3368c7557b..5fb7e1386fa 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java @@ -36,6 +36,9 @@ package java.util.concurrent; 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.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -910,11 +913,12 @@ else if (p == (p = p.next)) { advance(null); } + @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean hasNext() { return nextNode != null; } - public final E next() { + public final E next(@NonEmpty Itr this) { final Node p; if ((p = nextNode) == null) throw new NoSuchElementException(); E e = nextItem; @@ -1230,6 +1234,7 @@ public boolean offer(E e) { * @return {@code true} (as specified by {@link Collection#add}) * @throws NullPointerException if the specified element is null */ + @EnsuresNonEmpty("this") public boolean add(E e) { xfer(e, true, ASYNC, 0L); return true; @@ -1375,6 +1380,7 @@ else if (item == null) * @return {@code true} if this queue contains no elements */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return firstDataNode() == null; } @@ -1465,6 +1471,7 @@ else if (!p.isData) * @return {@code true} if this queue contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied @Nullable @UnknownSignedness Object o) { if (o == null) return false; restartFromHead: for (;;) { 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 420cae708ee..d14dc3a7c07 100644 --- a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java @@ -36,6 +36,9 @@ package java.util.concurrent; 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.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -455,6 +458,7 @@ private void heapify() { * priority queue's ordering * @throws NullPointerException if the specified element is null */ + @EnsuresNonEmpty("this") public boolean add(E e) { return offer(e); } @@ -697,6 +701,7 @@ void removeEq(Object o) { * @return {@code true} if this queue contains the specified element */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied @Nullable @UnknownSignedness Object o) { final ReentrantLock lock = this.lock; lock.lock(); @@ -865,11 +870,12 @@ final class Itr implements Iterator { this.array = array; } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor < array.length; } - public E next() { + public E next(@NonEmpty Itr this) { if (cursor >= array.length) throw new NoSuchElementException(); return (E)array[lastRet = cursor++]; 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 ec94d37f010..764b24f6333 100644 --- a/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java +++ b/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java @@ -35,6 +35,9 @@ package java.util.concurrent; +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.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; import org.checkerframework.checker.signedness.qual.UnknownSignedness; @@ -1037,6 +1040,7 @@ private int indexOf(Object x) { } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object x) { final ReentrantLock lock = this.lock; lock.lock(); @@ -1082,6 +1086,7 @@ public int size() { } @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return size() == 0; } @@ -1131,6 +1136,7 @@ public void put(Runnable e) { offer(e); } + @EnsuresNonEmpty("this") public boolean add(Runnable e) { return offer(e); } @@ -1337,11 +1343,12 @@ private class Itr implements Iterator { this.array = array; } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor < array.length; } - public Runnable next() { + public Runnable next(@NonEmpty Itr this) { if (cursor >= array.length) throw new NoSuchElementException(); return array[lastRet = cursor++]; 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 d9f3391e35e..7039049aa9d 100644 --- a/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java @@ -37,6 +37,7 @@ package java.util.concurrent; import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; @@ -935,6 +936,7 @@ public E poll() { * @return {@code true} */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return true; } @@ -975,6 +977,7 @@ public void clear() { * @return {@code false} */ @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@GuardSatisfied @Nullable @UnknownSignedness Object o) { return false; } diff --git a/src/java.base/share/classes/java/util/jar/Attributes.java b/src/java.base/share/classes/java/util/jar/Attributes.java index 0f3aca870e8..598b52fad7d 100644 --- a/src/java.base/share/classes/java/util/jar/Attributes.java +++ b/src/java.base/share/classes/java/util/jar/Attributes.java @@ -26,6 +26,7 @@ package java.util.jar; import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -264,6 +265,7 @@ public int size() { * Returns true if this Map contains no attributes. */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return map.isEmpty(); } diff --git a/src/java.base/share/classes/java/util/jar/JarFile.java b/src/java.base/share/classes/java/util/jar/JarFile.java index e7137e1ede9..66b56d786d2 100644 --- a/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/src/java.base/share/classes/java/util/jar/JarFile.java @@ -26,6 +26,8 @@ package java.util.jar; import org.checkerframework.checker.interning.qual.Interned; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.common.value.qual.StringVal; import org.checkerframework.framework.qual.AnnotatedFor; @@ -1113,6 +1115,7 @@ Enumeration entries2() { JarEntry entry; + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasMoreElements() { if (entry != null) { return true; @@ -1128,7 +1131,7 @@ public boolean hasMoreElements() { return false; } - public JarEntry nextElement() { + public JarEntry nextElement(/*@NonEmpty Enumeration this*/) { if (hasMoreElements()) { JarEntry je = entry; entry = null; @@ -1167,6 +1170,7 @@ private Enumeration unsignedEntryNames() { * Grab entries from ZIP directory but screen out * metadata. */ + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasMoreElements() { if (name != null) { return true; @@ -1184,7 +1188,7 @@ public boolean hasMoreElements() { return false; } - public String nextElement() { + public String nextElement(/*@NonEmpty Enumeration this*/) { if (hasMoreElements()) { String value = name; name = null; diff --git a/src/java.base/share/classes/java/util/jar/JarVerifier.java b/src/java.base/share/classes/java/util/jar/JarVerifier.java index 1c110166754..632455815f3 100644 --- a/src/java.base/share/classes/java/util/jar/JarVerifier.java +++ b/src/java.base/share/classes/java/util/jar/JarVerifier.java @@ -25,6 +25,9 @@ package java.util.jar; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; + import java.io.*; import java.net.URL; import java.util.*; @@ -698,6 +701,7 @@ public synchronized Enumeration entryNames(JarFile jar, final CodeSource String name; + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasMoreElements() { if (name != null) { return true; @@ -717,7 +721,7 @@ public boolean hasMoreElements() { return false; } - public String nextElement() { + public String nextElement(/*@NonEmpty Enumeration this*/) { if (hasMoreElements()) { String value = name; name = null; @@ -741,6 +745,7 @@ public Enumeration entries2(final JarFile jar, Enumeration e Enumeration signers = null; JarEntry entry; + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasMoreElements() { if (entry != null) { return true; @@ -766,7 +771,7 @@ public boolean hasMoreElements() { return false; } - public JarEntry nextElement() { + public JarEntry nextElement(/*@NonEmpty Enumeration this*/) { if (hasMoreElements()) { JarEntry je = entry; map.remove(je.getName()); @@ -794,6 +799,7 @@ private Enumeration unsignedEntryNames(JarFile jar) { * Grab entries from ZIP directory but screen out * metadata. */ + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasMoreElements() { if (name != null) { return true; @@ -813,7 +819,7 @@ public boolean hasMoreElements() { return false; } - public String nextElement() { + public String nextElement(/*@NonEmpty Enumeration this*/) { if (hasMoreElements()) { String value = name; name = null; diff --git a/src/java.base/share/classes/java/util/regex/IntHashSet.java b/src/java.base/share/classes/java/util/regex/IntHashSet.java index d4d9183843e..e1350918c0d 100644 --- a/src/java.base/share/classes/java/util/regex/IntHashSet.java +++ b/src/java.base/share/classes/java/util/regex/IntHashSet.java @@ -25,6 +25,7 @@ package java.util.regex; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.dataflow.qual.Pure; import java.util.Arrays; @@ -45,6 +46,7 @@ public IntHashSet() { } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(int i) { int h = hashes[i % hashes.length]; while (h != -1) { 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 e9a00f5b50d..c916d2f30ac 100644 --- a/src/java.base/share/classes/java/util/regex/Matcher.java +++ b/src/java.base/share/classes/java/util/regex/Matcher.java @@ -29,6 +29,8 @@ import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.interning.qual.UsesObjectEquals; 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.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; @@ -1319,7 +1321,7 @@ class MatchResultIterator implements Iterator { String textAsString; @Override - public MatchResult next() { + public MatchResult next(@NonEmpty MatchResultIterator this) { if (expectedCount >= 0 && expectedCount != modCount) throw new ConcurrentModificationException(); @@ -1331,6 +1333,7 @@ public MatchResult next() { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (state >= 0) return state == 1; 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 7efb6f58a0a..e6f4f5e3905 100644 --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -27,6 +27,8 @@ import org.checkerframework.checker.interning.qual.UsesObjectEquals; 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.regex.qual.PolyRegex; import org.checkerframework.checker.regex.qual.Regex; import org.checkerframework.checker.signedness.qual.SignedPositive; @@ -5868,7 +5870,7 @@ class MatcherIterator implements Iterator { // > 0 if there are N next empty elements private int emptyElementCount; - public String next() { + public String next(@NonEmpty MatcherIterator this) { if (!hasNext()) throw new NoSuchElementException(); @@ -5882,6 +5884,7 @@ public String next() { } } + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (matcher == null) { matcher = matcher(input); diff --git a/src/java.base/share/classes/java/util/stream/AbstractSpinedBuffer.java b/src/java.base/share/classes/java/util/stream/AbstractSpinedBuffer.java index e3034014ef2..e766529d266 100644 --- a/src/java.base/share/classes/java/util/stream/AbstractSpinedBuffer.java +++ b/src/java.base/share/classes/java/util/stream/AbstractSpinedBuffer.java @@ -25,6 +25,7 @@ */ package java.util.stream; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.dataflow.qual.Pure; /** @@ -101,6 +102,7 @@ protected AbstractSpinedBuffer(int initialCapacity) { * Is the buffer currently empty? */ @Pure + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return (spineIndex == 0) && (elementIndex == 0); } diff --git a/src/java.base/share/classes/java/util/stream/Stream.java b/src/java.base/share/classes/java/util/stream/Stream.java index fe32b88f980..05bac437794 100644 --- a/src/java.base/share/classes/java/util/stream/Stream.java +++ b/src/java.base/share/classes/java/util/stream/Stream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,10 @@ package java.util.stream; 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.nullness.qual.PolyNull; import org.checkerframework.dataflow.qual.SideEffectFree; @@ -201,7 +205,7 @@ public interface Stream extends BaseStream> { * function to apply to each element * @return the new stream */ - Stream map(Function mapper); + @PolyNonEmpty Stream map(@PolyNonEmpty Stream this, Function mapper); /** * Returns an {@code IntStream} consisting of the results of applying the @@ -583,7 +587,7 @@ default DoubleStream mapMultiToDouble(BiConsumer distinct(); + @PolyNonEmpty Stream distinct(@PolyNonEmpty Stream this); /** * Returns a stream consisting of the elements of this stream, sorted @@ -599,7 +603,7 @@ default DoubleStream mapMultiToDouble(BiConsumer sorted(); + @PolyNonEmpty Stream sorted(@PolyNonEmpty Stream this); /** * Returns a stream consisting of the elements of this stream, sorted @@ -616,7 +620,7 @@ default DoubleStream mapMultiToDouble(BiConsumer sorted(Comparator comparator); + @PolyNonEmpty Stream sorted(@PolyNonEmpty Stream this, Comparator comparator); /** * Returns a stream consisting of the elements of this stream, additionally @@ -889,7 +893,7 @@ default Stream dropWhile(Predicate predicate) { * type} is {@code Object}, containing the elements of this stream */ @SideEffectFree - @PolyNull Object[] toArray(Stream<@PolyNull T> this); + @PolyNull Object @PolyNonEmpty[] toArray(@PolyNonEmpty Stream<@PolyNull T> this); /** * Returns an array containing the elements of this stream, using the @@ -1295,7 +1299,8 @@ default List toList() { * @return {@code true} if any elements of the stream match the provided * predicate, otherwise {@code false} */ - boolean anyMatch(Predicate predicate); + @EnsuresNonEmptyIf(result = true, expression = "this") + boolean anyMatch(Stream this, Predicate predicate); /** * Returns whether all elements of this stream match the provided predicate. @@ -1318,7 +1323,8 @@ default List toList() { * @return {@code true} if either all elements of the stream match the * provided predicate or the stream is empty, otherwise {@code false} */ - boolean allMatch(Predicate predicate); + @EnsuresNonEmptyIf(result = true, expression = "this") + boolean allMatch(Stream this, Predicate predicate); /** * Returns whether no elements of this stream match the provided predicate. @@ -1341,7 +1347,8 @@ default List toList() { * @return {@code true} if either no elements of the stream match the * provided predicate or the stream is empty, otherwise {@code false} */ - boolean noneMatch(Predicate predicate); + @EnsuresNonEmptyIf(result = false, expression = "this") + boolean noneMatch(Stream this, Predicate predicate); /** * Returns an {@link Optional} describing the first element of this stream, @@ -1406,7 +1413,7 @@ public static Stream empty() { * @param the type of stream elements * @return a singleton sequential stream */ - public static Stream of(T t) { + public static @NonEmpty Stream of(T t) { return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false); } @@ -1434,7 +1441,7 @@ public static Stream ofNullable(@Nullable T t) { */ @SafeVarargs @SuppressWarnings("varargs") // Creating a stream from an array is safe - public static Stream of(T... values) { + public static @PolyNonEmpty Stream of(T @PolyNonEmpty... values) { return Arrays.stream(values); } @@ -1658,7 +1665,8 @@ public interface Builder extends Consumer { * the built state */ @Override - void accept(T t); + @EnsuresNonEmpty("this") + void accept(Stream.Builder this, T t); /** * Adds an element to the stream being built. @@ -1675,7 +1683,7 @@ public interface Builder extends Consumer { * @throws IllegalStateException if the builder has already transitioned to * the built state */ - default Builder add(Stream.@GuardSatisfied Builder this, T t) { + default @NonEmpty Builder add(Stream.@GuardSatisfied Builder this, T t) { accept(t); return this; } @@ -1689,7 +1697,7 @@ default Builder add(Stream.@GuardSatisfied Builder this, T t) { * @throws IllegalStateException if the builder has already transitioned to * the built state */ - Stream build(); + @PolyNonEmpty Stream build(Stream.@PolyNonEmpty Builder this); } } 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 48eae198e67..cb4617c3ad5 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -31,6 +31,8 @@ import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.interning.qual.UsesObjectEquals; import org.checkerframework.checker.mustcall.qual.MustCallAlias; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.signedness.qual.SignedPositive; import org.checkerframework.dataflow.qual.Pure; @@ -498,23 +500,25 @@ public ZipEntryIterator(int entryCount) { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasMoreElements() { return hasNext(); } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return i < entryCount; } @Override - public T nextElement() { + public T nextElement(@NonEmpty ZipEntryIterator this) { return next(); } @Override @SuppressWarnings("unchecked") - public T next() { + public T next(@NonEmpty ZipEntryIterator this) { synchronized (ZipFile.this) { ensureOpen(); if (!hasNext()) { diff --git a/src/java.base/share/classes/javax/crypto/CryptoPermissions.java b/src/java.base/share/classes/javax/crypto/CryptoPermissions.java index ced2e2bd88b..68db58fc4f5 100644 --- a/src/java.base/share/classes/javax/crypto/CryptoPermissions.java +++ b/src/java.base/share/classes/javax/crypto/CryptoPermissions.java @@ -25,6 +25,9 @@ package javax.crypto; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; +import org.checkerframework.checker.nonempty.qual.NonEmpty; + import java.security.*; import java.util.Enumeration; import java.util.Hashtable; @@ -114,6 +117,7 @@ void load(InputStream in) * contain any CryptoPermission objects; otherwise, returns * false. */ + @EnsuresNonEmptyIf(result = false, expression = "this") boolean isEmpty() { return perms.isEmpty(); } @@ -478,6 +482,7 @@ final class PermissionsEnumerator implements Enumeration { } @Override + @EnsuresNonEmptyIf(result = true, expression = "this") public synchronized boolean hasMoreElements() { // if we enter with permissionimpl null, we know // there are no more left. @@ -500,7 +505,7 @@ public synchronized boolean hasMoreElements() { } @Override - public synchronized Permission nextElement() { + public synchronized Permission nextElement(@NonEmpty PermissionsEnumerator this) { // hasMoreElements will update permset to the next permset // with something in it... diff --git a/src/java.base/share/classes/javax/crypto/CryptoPolicyParser.java b/src/java.base/share/classes/javax/crypto/CryptoPolicyParser.java index d2991852ff6..1894bd2813d 100644 --- a/src/java.base/share/classes/javax/crypto/CryptoPolicyParser.java +++ b/src/java.base/share/classes/javax/crypto/CryptoPolicyParser.java @@ -25,7 +25,9 @@ package javax.crypto; +import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.dataflow.qual.Pure; + import java.io.*; import java.util.Enumeration; import java.util.Hashtable; @@ -574,6 +576,7 @@ boolean remove(CryptoPermissionEntry pe) } @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") boolean contains(CryptoPermissionEntry pe) { return permissionEntries.contains(pe); 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 3f4936c2da8..d67850140cd 100644 --- a/src/java.base/share/classes/javax/security/auth/Subject.java +++ b/src/java.base/share/classes/javax/security/auth/Subject.java @@ -25,6 +25,9 @@ package javax.security.auth; +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.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -1123,9 +1126,10 @@ public Iterator iterator() { return new Iterator() { ListIterator i = list.listIterator(0); + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() {return i.hasNext();} - public E next() { + public E next(/*@NonEmpty Iterator this*/) { if (which != Subject.PRIV_CREDENTIAL_SET) { return i.next(); } @@ -1172,6 +1176,7 @@ public void remove() { }; } + @EnsuresNonEmpty("this") public boolean add(E o) { Objects.requireNonNull(o, @@ -1248,6 +1253,7 @@ public E run() { @SuppressWarnings("removal") @Pure + @EnsuresNonEmptyIf(result = true, expression = "this") public boolean contains(@UnknownSignedness Object o) { Objects.requireNonNull(o, @@ -1390,6 +1396,7 @@ public E run() { } } + @EnsuresNonEmptyIf(result = false, expression = "this") public boolean isEmpty() { return elements.isEmpty(); } @@ -1596,6 +1603,7 @@ public Iterator iterator() { } @Override + @EnsuresNonEmpty("this") public boolean add(T o) { if (!c.isAssignableFrom(o.getClass())) { diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index 52de1aea18c..99ee6786fea 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -89,6 +89,7 @@ exports org.checkerframework.checker.interning.qual; exports org.checkerframework.checker.lock.qual; exports org.checkerframework.checker.mustcall.qual; + exports org.checkerframework.checker.nonempty.qual; exports org.checkerframework.checker.nullness.qual; exports org.checkerframework.checker.optional.qual; exports org.checkerframework.checker.propkey.qual; 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 new file mode 100644 index 00000000000..d997df2fc83 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmpty.java @@ -0,0 +1,53 @@ +package org.checkerframework.checker.nonempty.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.InheritedAnnotation; +import org.checkerframework.framework.qual.PostconditionAnnotation; + +/** + * Indicates that a particular expression evaluates to a non-empty value, if the method terminates + * successfully. + * + *

This annotation applies to {@link java.util.Collection}, {@link java.util.Iterator}, {@link + * java.lang.Iterable}, and {@link java.util.Map}, but not {@link java.util.Optional}. + * + *

This postcondition annotation is useful for methods that make a value non-empty by side + * effect: + * + *


+ *   {@literal @}EnsuresNonEmpty("ids")
+ *   void addId(String id) {
+ *     ids.add(id);
+ *   }
+ * 
+ * + * It can also be used for a method that fails if a given value is empty, indicating that the + * argument is non-empty if the method returns normally: + * + *

+ *   /** Throws an exception if the argument is empty. */
+ *   {@literal @}EnsuresNonEmpty("#1")
+ *   void useTheMap(Map<T, U> arg) { ... }
+ * 
+ * + * @see NonEmpty + * @see org.checkerframework.checker.nonempty.NonEmptyChecker + * @checker_framework.manual #non-empty-checker Non-Empty Checker + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) +@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(); +} 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 new file mode 100644 index 00000000000..b5af54e90cd --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmptyIf.java @@ -0,0 +1,87 @@ +package org.checkerframework.checker.nonempty.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.ConditionalPostconditionAnnotation; +import org.checkerframework.framework.qual.InheritedAnnotation; + +/** + * Indicates that the specific expressions are non-empty, if the method returns the given result + * (either true or false). + * + *

Here are ways this conditional postcondition annotation can be used: + * + *

Method parameters: Suppose that a method has a parameter that is a list, and returns + * true if the length of the list is non-zero. You could annotate the method as follows: + * + *

 @EnsuresNonEmptyIf(result = true, expression = "#1")
+ *  public <T> boolean isLengthGreaterThanZero(List<T> items) { ... }
+ * 
+ * + * because, if {@code isLengthGreaterThanZero} returns true, then {@code items} was non-empty. Note + * that you can write more than one {@code @EnsuresNonEmptyIf} annotations on a single method. + * + *

Fields: The value expression can refer to fields, even private ones. For example: + * + *

 @EnsuresNonEmptyIf(result = true, expression = "this.orders")
+ *  public <T> boolean areOrdersActive() {
+ *    return this.orders != null && this.orders.size() > 0;
+ * }
+ * + * An {@code @EnsuresNonEmptyIf} annotation that refers to a private field is useful for verifying + * that a method establishes a property, even though client code cannot directly affect the field. + * + *

Method postconditions: Suppose that if a method {@code areOrdersActive()} returns true, + * then {@code getOrders()} will return a non-empty Map. You can express this relationship as: + * + *

 @EnsuresNonEmptyIf(result = true, expression = "this.getOrders()")
+ *  public <T> boolean areOrdersActive() {
+ *    return this.orders != null && this.orders.size() > 0;
+ * }
+ * + * @see NonEmpty + * @see EnsuresNonEmpty + * @checker_framework.manual #non-empty-checker Non-Empty Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) +@ConditionalPostconditionAnnotation(qualifier = NonEmpty.class) +@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(); + + /** + * 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. + * + * @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 new file mode 100644 index 00000000000..d5a7f8c15d5 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/NonEmpty.java @@ -0,0 +1,20 @@ +package org.checkerframework.checker.nonempty.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 {@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. + * + * @checker_framework.manual #non-empty-checker Non-Empty Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) +@SubtypeOf(UnknownNonEmpty.class) +public @interface NonEmpty {} 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 new file mode 100644 index 00000000000..dd538314595 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/PolyNonEmpty.java @@ -0,0 +1,20 @@ +package org.checkerframework.checker.nonempty.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 the Non-Empty type system. + * + * @checker_framework.manual #non-empty-checker Non-Empty Checker + * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@PolymorphicQualifier(UnknownNonEmpty.class) +public @interface PolyNonEmpty {} 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 new file mode 100644 index 00000000000..45b46d4233d --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/RequiresNonEmpty.java @@ -0,0 +1,96 @@ +package org.checkerframework.checker.nonempty.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.PreconditionAnnotation; + +/** + * Indicates a method precondition: the specified expressions that may be a {@link + * java.util.Collection collection}, {@link java.util.Iterator iterator}, {@link java.lang.Iterable + * iterable}, or {@link java.util.Map map} must be non-empty when the annotated method is invoked. + * + *

For example: + * + *

+ * import java.util.LinkedList;
+ * import java.util.List;
+ * import org.checkerframework.checker.nonempty.qual.NonEmpty;
+ * import org.checkerframework.checker.nonempty.qual.RequiresNonEmpty;
+ * import org.checkerframework.dataflow.qual.Pure;
+ *
+ * class MyClass {
+ *
+ *   List<String> list1 = new LinkedList<>();
+ *   List<String> list2;
+ *
+ *   @RequiresNonEmpty("list1")
+ *   @Pure
+ *   void m1() {}
+ *
+ *   @RequiresNonEmpty({"list1", "list2"})
+ *   @Pure
+ *   void m2() {}
+ *
+ *   @RequiresNonEmpty({"list1", "list2"})
+ *   void m3() {}
+ *
+ *   void m4() {}
+ *
+ *   void test(@NonEmpty List<String> l1, @NonEmpty List<String> l2) {
+ *     MyClass testClass = new MyClass();
+ *
+ *     testClass.m1(); // Compile-time error: m1 requires that list1 is @NonEmpty.
+ *
+ *     testClass.list1 = l1;
+ *     testClass.m1(); // OK
+ *
+ *     testClass.m2(); // Compile-time error: m2 requires that list2 is @NonEmpty
+ *
+ *     testClass.list2 = l2;
+ *     testClass.m2(); // OK
+ *
+ *     testClass.m4();
+ *
+ *     testClass.m2(); // Compile-time error: m4 is not pure and might have assigned a field.
+ *   }
+ * }
+ * 
+ * + * 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 + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.PARAMETER}) +@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(); + + /** + * 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. + * + * @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 new file mode 100644 index 00000000000..65900f7fa12 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/UnknownNonEmpty.java @@ -0,0 +1,22 @@ +package org.checkerframework.checker.nonempty.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; + +/** + * 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. + * + * @checker_framework.manual #non-empty-checker Non-Empty Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) +@DefaultQualifierInHierarchy +@SubtypeOf({}) +public @interface UnknownNonEmpty {} From 300156f87e172051a1596ff244f3f26e42c47522 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Wed, 26 Jun 2024 10:59:17 -0700 Subject: [PATCH 20/32] Augment README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2e7271e5835..22bff8194e9 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,8 @@ Replace the existing export lines present in exports. If no new packages were added, then there are likely going to be no changes to the `module-info.java` file. -Commit the changes, including any new `.java` files in a `qual/` directory. +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 From 5ceaadd22a48846eeb7d7833844dcde9974243f0 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 5 Jul 2024 13:32:21 -0700 Subject: [PATCH 21/32] Purity annotations --- .../share/classes/java/nio/file/Files.java | 63 +++++++++++++++++++ .../classes/java/util/regex/Matcher.java | 18 ++++++ 2 files changed, 81 insertions(+) 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 a7985256031..c932a778c7b 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -26,6 +26,7 @@ package java.nio.file; import org.checkerframework.checker.interning.qual.UsesObjectEquals; +import org.checkerframework.checker.lock.qual.ReleasesNoLocks; import org.checkerframework.checker.mustcall.qual.MustCall; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; @@ -164,6 +165,7 @@ private static Runnable asUncheckedRunnable(Closeable c) { * installed, the {@link SecurityManager#checkRead(String) checkRead} * method is invoked to check read access to the file. */ + @ReleasesNoLocks public static InputStream newInputStream(Path path, OpenOption... options) throws IOException { @@ -232,6 +234,7 @@ public static InputStream newInputStream(Path path, OpenOption... options) * invoked to check delete access if the file is opened with the * {@code DELETE_ON_CLOSE} option. */ + @ReleasesNoLocks public static OutputStream newOutputStream(Path path, OpenOption... options) throws IOException { @@ -382,6 +385,7 @@ public static OutputStream newOutputStream(Path path, OpenOption... options) * * @see java.nio.channels.FileChannel#open(Path,Set,FileAttribute[]) */ + @ReleasesNoLocks public static SeekableByteChannel newByteChannel(Path path, Set options, FileAttribute... attrs) @@ -429,6 +433,7 @@ public static SeekableByteChannel newByteChannel(Path path, * * @see java.nio.channels.FileChannel#open(Path,OpenOption[]) */ + @ReleasesNoLocks public static SeekableByteChannel newByteChannel(Path path, OpenOption... options) throws IOException { @@ -450,6 +455,7 @@ private static class AcceptAllFilter private AcceptAllFilter() { } @Override + @ReleasesNoLocks public boolean accept(Path entry) { return true; } static final AcceptAllFilter FILTER = new AcceptAllFilter(); @@ -486,6 +492,7 @@ private AcceptAllFilter() { } * installed, the {@link SecurityManager#checkRead(String) checkRead} * method is invoked to check read access to the directory. */ + @ReleasesNoLocks public static @MustCall("close") DirectoryStream newDirectoryStream(Path dir) throws IOException { @@ -541,6 +548,7 @@ private AcceptAllFilter() { } * installed, the {@link SecurityManager#checkRead(String) checkRead} * method is invoked to check read access to the directory. */ + @ReleasesNoLocks public static @MustCall("close") DirectoryStream newDirectoryStream(Path dir, String glob) throws IOException { @@ -553,6 +561,7 @@ private AcceptAllFilter() { } final PathMatcher matcher = fs.getPathMatcher("glob:" + glob); DirectoryStream.Filter filter = new DirectoryStream.Filter<>() { @Override + @ReleasesNoLocks public boolean accept(Path entry) { return matcher.matches(entry.getFileName()); } @@ -617,6 +626,7 @@ public boolean accept(Path entry) { * installed, the {@link SecurityManager#checkRead(String) checkRead} * method is invoked to check read access to the directory. */ + @ReleasesNoLocks public static @MustCall("close") DirectoryStream newDirectoryStream(Path dir, DirectoryStream.Filter filter) throws IOException @@ -662,6 +672,7 @@ public boolean accept(Path entry) { * installed, the {@link SecurityManager#checkWrite(String) checkWrite} * method is invoked to check write access to the new file. */ + @ReleasesNoLocks public static Path createFile(Path path, FileAttribute... attrs) throws IOException { @@ -704,6 +715,7 @@ public static Path createFile(Path path, FileAttribute... attrs) * installed, the {@link SecurityManager#checkWrite(String) checkWrite} * method is invoked to check write access to the new directory. */ + @ReleasesNoLocks public static Path createDirectory(Path dir, FileAttribute... attrs) throws IOException { @@ -755,6 +767,7 @@ public static Path createDirectory(Path dir, FileAttribute... attrs) * SecurityManager#checkPropertyAccess(String) checkPropertyAccess} * method to check access to the system property {@code user.dir} */ + @ReleasesNoLocks public static Path createDirectories(Path dir, FileAttribute... attrs) throws IOException { @@ -879,6 +892,7 @@ private static void createAndCheckIsDirectory(Path dir, * installed, the {@link SecurityManager#checkWrite(String) checkWrite} * method is invoked to check write access to the file. */ + @ReleasesNoLocks public static Path createTempFile(Path dir, String prefix, String suffix, @@ -925,6 +939,7 @@ public static Path createTempFile(Path dir, * installed, the {@link SecurityManager#checkWrite(String) checkWrite} * method is invoked to check write access to the file. */ + @ReleasesNoLocks public static Path createTempFile(String prefix, String suffix, FileAttribute... attrs) @@ -978,6 +993,7 @@ public static Path createTempFile(String prefix, * method is invoked to check write access when creating the * directory. */ + @ReleasesNoLocks public static Path createTempDirectory(Path dir, String prefix, FileAttribute... attrs) @@ -1020,6 +1036,7 @@ public static Path createTempDirectory(Path dir, * method is invoked to check write access when creating the * directory. */ + @ReleasesNoLocks public static Path createTempDirectory(String prefix, FileAttribute... attrs) throws IOException @@ -1072,6 +1089,7 @@ public static Path createTempDirectory(String prefix, * or its {@link SecurityManager#checkWrite(String) checkWrite} * method denies write access to the path of the symbolic link. */ + @ReleasesNoLocks public static Path createSymbolicLink(Path link, Path target, FileAttribute... attrs) throws IOException @@ -1118,6 +1136,7 @@ public static Path createSymbolicLink(Path link, Path target, * method denies write access to either the link or the * existing file. */ + @ReleasesNoLocks public static Path createLink(Path link, Path existing) throws IOException { provider(link).createLink(link, existing); return link; @@ -1158,6 +1177,7 @@ public static Path createLink(Path link, Path existing) throws IOException { * installed, the {@link SecurityManager#checkDelete(String)} method * is invoked to check delete access to the file */ + @ReleasesNoLocks public static void delete(Path path) throws IOException { provider(path).delete(path); } @@ -1197,6 +1217,7 @@ public static void delete(Path path) throws IOException { * installed, the {@link SecurityManager#checkDelete(String)} method * is invoked to check delete access to the file. */ + @ReleasesNoLocks public static boolean deleteIfExists(Path path) throws IOException { return provider(path).deleteIfExists(path); } @@ -1306,6 +1327,7 @@ public static boolean deleteIfExists(Path path) throws IOException { * copied the security manager is invoked to check {@link * LinkPermission}{@code ("symbolic")}. */ + @ReleasesNoLocks public static Path copy(Path source, Path target, CopyOption... options) throws IOException { @@ -1433,6 +1455,7 @@ public static Path copy(Path source, Path target, CopyOption... options) * method is invoked to check write access to both the source and * target file. */ + @ReleasesNoLocks public static Path move(Path source, Path target, CopyOption... options) throws IOException { @@ -1475,6 +1498,7 @@ public static Path move(Path source, Path target, CopyOption... options) * is installed, it checks that {@code FilePermission} has been * granted with the "{@code readlink}" action to read the link. */ + @ReleasesNoLocks public static Path readSymbolicLink(Path link) throws IOException { return provider(link).readSymbolicLink(link); } @@ -1504,6 +1528,7 @@ public static Path readSymbolicLink(Path link) throws IOException { * addition it checks * {@link RuntimePermission}{@code ("getFileStoreAttributes")} */ + @ReleasesNoLocks public static FileStore getFileStore(Path path) throws IOException { return provider(path).getFileStore(path); } @@ -1600,6 +1625,7 @@ public static boolean isSameFile(Path path, Path path2) throws IOException { * * @since 12 */ + @ReleasesNoLocks public static long mismatch(Path path, Path path2) throws IOException { if (isSameFile(path, path2)) { return -1; @@ -1735,6 +1761,7 @@ private static List loadInstalledDetectors() { * If a security manager is installed and it denies an unspecified * permission required by a file type detector implementation. */ + @ReleasesNoLocks public static String probeContentType(Path path) throws IOException { @@ -1793,6 +1820,7 @@ public static String probeContentType(Path path) * @return a file attribute view of the specified type, or {@code null} if * the attribute view type is not available */ + @ReleasesNoLocks public static V getFileAttributeView(Path path, Class type, LinkOption... options) @@ -1855,6 +1883,7 @@ public static V getFileAttributeView(Path path, * method is invoked to read security sensitive attributes then the * security manager may be invoke to check for additional permissions. */ + @ReleasesNoLocks public static A readAttributes(Path path, Class type, LinkOption... options) @@ -1924,6 +1953,7 @@ public static A readAttributes(Path path, * to set security sensitive attributes then the security manager * may be invoked to check for additional permissions. */ + @ReleasesNoLocks public static Path setAttribute(Path path, String attribute, Object value, LinkOption... options) throws IOException @@ -1985,6 +2015,7 @@ public static Path setAttribute(Path path, String attribute, Object value, * to read security sensitive attributes then the security manager * may be invoked to check for additional permissions. */ + @ReleasesNoLocks public static Object getAttribute(Path path, String attribute, LinkOption... options) throws IOException @@ -2089,6 +2120,7 @@ public static Object getAttribute(Path path, String attribute, * to read security sensitive attributes then the security manager * may be invoke to check for additional permissions. */ + @ReleasesNoLocks public static Map readAttributes(Path path, String attributes, LinkOption... options) throws IOException @@ -2130,6 +2162,7 @@ public static Map readAttributes(Path path, String attributes, * or its {@link SecurityManager#checkRead(String) checkRead} method * denies read access to the file. */ + @ReleasesNoLocks public static Set getPosixFilePermissions(Path path, LinkOption... options) throws IOException @@ -2168,6 +2201,7 @@ public static Set getPosixFilePermissions(Path path, * or its {@link SecurityManager#checkWrite(String) checkWrite} * method denies write access to the file. */ + @ReleasesNoLocks public static Path setPosixFilePermissions(Path path, Set perms) throws IOException @@ -2206,6 +2240,7 @@ public static Path setPosixFilePermissions(Path path, * or its {@link SecurityManager#checkRead(String) checkRead} method * denies read access to the file. */ + @ReleasesNoLocks public static UserPrincipal getOwner(Path path, LinkOption... options) throws IOException { FileOwnerAttributeView view = getFileAttributeView(path, FileOwnerAttributeView.class, options); @@ -2253,6 +2288,7 @@ public static UserPrincipal getOwner(Path path, LinkOption... options) throws IO * @see FileSystem#getUserPrincipalLookupService * @see java.nio.file.attribute.UserPrincipalLookupService */ + @ReleasesNoLocks public static Path setOwner(Path path, UserPrincipal owner) throws IOException { @@ -2411,6 +2447,7 @@ public static boolean isRegularFile(Path path, LinkOption... options) { * * @see BasicFileAttributes#lastModifiedTime */ + @ReleasesNoLocks public static FileTime getLastModifiedTime(Path path, LinkOption... options) throws IOException { @@ -2450,6 +2487,7 @@ public static FileTime getLastModifiedTime(Path path, LinkOption... options) * * @see BasicFileAttributeView#setTimes */ + @ReleasesNoLocks public static Path setLastModifiedTime(Path path, FileTime time) throws IOException { @@ -2479,6 +2517,7 @@ public static Path setLastModifiedTime(Path path, FileTime time) * * @see BasicFileAttributes#size */ + @ReleasesNoLocks public static long size(Path path) throws IOException { return readAttributes(path, BasicFileAttributes.class).size(); } @@ -2810,6 +2849,7 @@ public static boolean isExecutable(Path path) { * @throws IOException * if an I/O error is thrown by a visitor method */ + @ReleasesNoLocks public static Path walkFileTree(Path start, Set options, int maxDepth, @@ -2896,6 +2936,7 @@ public static Path walkFileTree(Path start, * @throws IOException * if an I/O error is thrown by a visitor method */ + @ReleasesNoLocks public static Path walkFileTree(Path start, FileVisitor visitor) throws IOException { @@ -2935,6 +2976,7 @@ public static Path walkFileTree(Path start, FileVisitor visitor) * * @see #readAllLines */ + @ReleasesNoLocks public static BufferedReader newBufferedReader(Path path, Charset cs) throws IOException { @@ -2971,6 +3013,7 @@ public static BufferedReader newBufferedReader(Path path, Charset cs) * * @since 1.8 */ + @ReleasesNoLocks public static BufferedReader newBufferedReader(Path path) throws IOException { return newBufferedReader(path, UTF_8.INSTANCE); } @@ -3020,6 +3063,7 @@ public static BufferedReader newBufferedReader(Path path) throws IOException { * * @see #write(Path,Iterable,Charset,OpenOption[]) */ + @ReleasesNoLocks public static BufferedWriter newBufferedWriter(Path path, Charset cs, OpenOption... options) throws IOException @@ -3070,6 +3114,7 @@ public static BufferedWriter newBufferedWriter(Path path, Charset cs, * * @since 1.8 */ + @ReleasesNoLocks public static BufferedWriter newBufferedWriter(Path path, OpenOption... options) throws IOException { @@ -3141,6 +3186,7 @@ public static BufferedWriter newBufferedWriter(Path path, OpenOption... options) * manager's {@link SecurityManager#checkDelete(String) checkDelete} * method is invoked to check that an existing file can be deleted. */ + @ReleasesNoLocks public static long copy(InputStream in, Path target, CopyOption... options) throws IOException { @@ -3225,6 +3271,7 @@ public static long copy(InputStream in, Path target, CopyOption... options) * installed, the {@link SecurityManager#checkRead(String) checkRead} * method is invoked to check read access to the file. */ + @ReleasesNoLocks public static long copy(Path source, OutputStream out) throws IOException { // ensure not null before opening file Objects.requireNonNull(out); @@ -3304,6 +3351,7 @@ private static byte[] read(InputStream source, int initialSize) throws IOExcepti * installed, the {@link SecurityManager#checkRead(String) checkRead} * method is invoked to check read access to the file. */ + @SideEffectFree public static byte[] readAllBytes(Path path) throws IOException { try (SeekableByteChannel sbc = Files.newByteChannel(path); InputStream in = Channels.newInputStream(sbc)) { @@ -3341,6 +3389,7 @@ public static byte[] readAllBytes(Path path) throws IOException { * * @since 11 */ + @SideEffectFree public static String readString(Path path) throws IOException { return readString(path, UTF_8.INSTANCE); } @@ -3379,6 +3428,7 @@ public static String readString(Path path) throws IOException { * * @since 11 */ + @SideEffectFree public static String readString(Path path, Charset cs) throws IOException { Objects.requireNonNull(path); Objects.requireNonNull(cs); @@ -3428,6 +3478,7 @@ public static String readString(Path path, Charset cs) throws IOException { * * @see #newBufferedReader */ + @SideEffectFree public static List readAllLines(Path path, Charset cs) throws IOException { try (BufferedReader reader = newBufferedReader(path, cs)) { List result = new ArrayList<>(); @@ -3469,6 +3520,7 @@ public static List readAllLines(Path path, Charset cs) throws IOExceptio * * @since 1.8 */ + @SideEffectFree public static List readAllLines(Path path) throws IOException { return readAllLines(path, UTF_8.INSTANCE); } @@ -3523,6 +3575,7 @@ public static List readAllLines(Path path) throws IOException { * invoked to check delete access if the file is opened with the * {@code DELETE_ON_CLOSE} option. */ + @ReleasesNoLocks public static Path write(Path path, @PolySigned byte[] bytes, OpenOption... options) throws IOException { @@ -3591,6 +3644,7 @@ public static Path write(Path path, @PolySigned byte[] bytes, OpenOption... opti * invoked to check delete access if the file is opened with the * {@code DELETE_ON_CLOSE} option. */ + @ReleasesNoLocks public static Path write(Path path, Iterable lines, Charset cs, OpenOption... options) throws IOException @@ -3645,6 +3699,7 @@ public static Path write(Path path, Iterable lines, * * @since 1.8 */ + @ReleasesNoLocks public static Path write(Path path, Iterable lines, OpenOption... options) @@ -3688,6 +3743,7 @@ public static Path write(Path path, * * @since 11 */ + @ReleasesNoLocks public static Path writeString(Path path, CharSequence csq, OpenOption... options) throws IOException { @@ -3740,6 +3796,7 @@ public static Path writeString(Path path, CharSequence csq, OpenOption... option * * @since 11 */ + @ReleasesNoLocks public static Path writeString(Path path, CharSequence csq, Charset cs, OpenOption... options) throws IOException { @@ -3808,6 +3865,7 @@ public static Path writeString(Path path, CharSequence csq, Charset cs, OpenOpti * @see #newDirectoryStream(Path) * @since 1.8 */ + @ReleasesNoLocks public static @MustCall("close") Stream list(Path dir) throws IOException { DirectoryStream ds = Files.newDirectoryStream(dir); try { @@ -3931,6 +3989,7 @@ public Path next(/*@NonEmpty Iterator this*/) { * if an I/O error is thrown when accessing the starting file. * @since 1.8 */ + @ReleasesNoLocks public static @MustCall("close") Stream walk(Path start, int maxDepth, FileVisitOption... options) @@ -3990,6 +4049,7 @@ public Path next(/*@NonEmpty Iterator this*/) { * @see #walk(Path, int, FileVisitOption...) * @since 1.8 */ + @ReleasesNoLocks public static @MustCall("close") Stream walk(Path start, FileVisitOption... options) throws IOException { return walk(start, Integer.MAX_VALUE, options); } @@ -4048,6 +4108,7 @@ public Path next(/*@NonEmpty Iterator this*/) { * @see #walk(Path, int, FileVisitOption...) * @since 1.8 */ + @ReleasesNoLocks public static @MustCall("close") Stream find(Path start, int maxDepth, BiPredicate matcher, @@ -4142,6 +4203,7 @@ public Path next(/*@NonEmpty Iterator this*/) { * @see java.io.BufferedReader#lines() * @since 1.8 */ + @SideEffectFree public static @MustCall("close") Stream lines(Path path, Charset cs) throws IOException { // Use the good splitting spliterator if: // 1) the path is associated with the default file system; @@ -4244,6 +4306,7 @@ private static Stream createBufferedReaderLinesStream(BufferedReader br) * * @since 1.8 */ + @SideEffectFree public static @MustCall("close") Stream lines(Path path) throws IOException { return lines(path, UTF_8.INSTANCE); } 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 c916d2f30ac..dc477594b56 100644 --- a/src/java.base/share/classes/java/util/regex/Matcher.java +++ b/src/java.base/share/classes/java/util/regex/Matcher.java @@ -29,6 +29,7 @@ import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.interning.qual.UsesObjectEquals; import org.checkerframework.checker.lock.qual.GuardSatisfied; +import org.checkerframework.checker.lock.qual.ReleasesNoLocks; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.nullness.qual.Nullable; @@ -269,6 +270,7 @@ * * @return The pattern for which this matcher was created */ + @Pure public Pattern pattern() { return parentPattern; } @@ -281,10 +283,12 @@ public Pattern pattern() { * @return a {@code MatchResult} with the state of this matcher * @since 1.5 */ + @SideEffectFree public MatchResult toMatchResult() { return toMatchResult(text.toString()); } + @SideEffectFree private MatchResult toMatchResult(String text) { return new ImmutableMatchResult(this.first, this.last, @@ -311,12 +315,14 @@ private static class ImmutableMatchResult implements MatchResult { } @Override + @Pure public int start() { checkMatch(); return first; } @Override + @Pure public int start(int group) { checkMatch(); if (group < 0 || group > groupCount) @@ -325,12 +331,14 @@ public int start(int group) { } @Override + @Pure public int end() { checkMatch(); return last; } @Override + @Pure public int end(int group) { checkMatch(); if (group < 0 || group > groupCount) @@ -339,17 +347,20 @@ public int end(int group) { } @Override + @Pure public int groupCount() { return groupCount; } @Override + @SideEffectFree public String group() { checkMatch(); return group(0); } @Override + @SideEffectFree public String group(int group) { checkMatch(); if (group < 0 || group > groupCount) @@ -518,6 +529,7 @@ public Matcher reset(CharSequence input) { * with the given name * @since 1.8 */ + @Pure public int start(String name) { return groups[getMatchedGroupIndex(name) * 2]; } @@ -592,6 +604,7 @@ public int start(String name) { * with the given name * @since 1.8 */ + @Pure public int end(String name) { return groups[getMatchedGroupIndex(name) * 2 + 1]; } @@ -728,6 +741,7 @@ public String group() { * @return {@code true} if, and only if, the entire region sequence * matches this matcher's pattern */ + @Pure public boolean matches() { return match(from, ENDANCHOR); } @@ -806,6 +820,7 @@ public boolean find(@NonNegative int start) { * @return {@code true} if, and only if, a prefix of the input * sequence matches this matcher's pattern */ + @Pure public boolean lookingAt() { return match(from, NOANCHOR); } @@ -825,6 +840,7 @@ public boolean lookingAt() { * @return A literal string replacement * @since 1.5 */ + @SideEffectFree public static String quoteReplacement(String s) { if ((s.indexOf('\\') == -1) && (s.indexOf('$') == -1)) return s; @@ -1192,6 +1208,7 @@ public StringBuilder appendTail(StringBuilder sb) { * by the replacement string, substituting captured subsequences * as needed */ + @SideEffectFree public String replaceAll(String replacement) { reset(); boolean result = find(); @@ -1265,6 +1282,7 @@ public String replaceAll(String replacement) { * matcher's state * @since 9 */ + @SideEffectFree public String replaceAll(Function replacer) { Objects.requireNonNull(replacer); reset(); From 2b17b856db35dfbf042202224170322589b28805 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 5 Jul 2024 09:46:14 -0700 Subject: [PATCH 22/32] Don't use `--filter=blob:none` --- azure-pipelines.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 6738eb17db2..790182be7ea 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -44,14 +44,14 @@ jobs: 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 --filter=blob:none -q https://github.com/plume-lib/git-scripts.git ; \ + 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 --filter=blob:none -q https://github.com/plume-lib/plume-scripts.git ; \ + 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 . @@ -96,7 +96,7 @@ jobs: steps: - checkout: self fetchDepth: 25 - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --filter=blob:none -q https://github.com/plume-lib/git-scripts.git + - 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 @@ -128,7 +128,7 @@ jobs: steps: - checkout: self fetchDepth: 25 - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --filter=blob:none -q https://github.com/plume-lib/git-scripts.git + - 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 @@ -152,7 +152,7 @@ jobs: steps: - checkout: self fetchDepth: 25 - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --filter=blob:none -q https://github.com/plume-lib/git-scripts.git + - 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 @@ -167,7 +167,7 @@ jobs: steps: - checkout: self fetchDepth: 25 - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --filter=blob:none -q https://github.com/plume-lib/git-scripts.git + - 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 @@ -181,7 +181,7 @@ jobs: steps: - checkout: self fetchDepth: 25 - - bash: mkdir -p /tmp/$USER && git -C /tmp/$USER clone --filter=blob:none -q https://github.com/plume-lib/git-scripts.git + - 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 From 27ccc4f32ed877d56c50b30bdaed5e73d6d21fd2 Mon Sep 17 00:00:00 2001 From: Adam Gent Date: Sat, 6 Jul 2024 14:04:09 -0400 Subject: [PATCH 23/32] jul.Properties get should be nullable The method was overridden so it lost its nullable annotation. --- src/java.base/share/classes/java/util/Properties.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/util/Properties.java b/src/java.base/share/classes/java/util/Properties.java index 0e4c1914117..4de5e039659 100644 --- a/src/java.base/share/classes/java/util/Properties.java +++ b/src/java.base/share/classes/java/util/Properties.java @@ -1313,7 +1313,7 @@ public boolean containsKey(@GuardSatisfied @Nullable @UnknownSignedness Object k } @Override - public Object get(Object key) { + public @Nullable Object get(Object key) { return map.get(key); } From 7c94506a4d9e41d8e82f294855fe5bc771d5002c Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sun, 7 Jul 2024 10:20:09 -0700 Subject: [PATCH 24/32] Diagnostics about cloning and updating jdk17u --- azure-pipelines.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 790182be7ea..e053f2470e7 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -59,7 +59,18 @@ jobs: # 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 @@ -67,9 +78,11 @@ jobs: 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` - echo "About to run: git pull --no-edit https://github.com/${CI_ORGANIZATION}/jdk ${CI_BRANCH}" 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 From fd7576eb66877662b99e160e879ee3f27ca334cb Mon Sep 17 00:00:00 2001 From: Adam Gent Date: Sun, 7 Jul 2024 13:20:51 -0400 Subject: [PATCH 25/32] StackWalker can take a nullable producing function --- src/java.base/share/classes/java/lang/StackWalker.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/lang/StackWalker.java b/src/java.base/share/classes/java/lang/StackWalker.java index 9f8a24f1e9e..c703e4caf6f 100644 --- a/src/java.base/share/classes/java/lang/StackWalker.java +++ b/src/java.base/share/classes/java/lang/StackWalker.java @@ -24,6 +24,8 @@ */ package java.lang; +import org.checkerframework.checker.nullness.qual.Nullable; + import jdk.internal.reflect.CallerSensitive; import java.lang.invoke.MethodType; @@ -484,7 +486,7 @@ private static EnumSet

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 j7gVvaDEF8SC) literal 269031 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 L|%q@ zWP4vIaJ(Kwt5RUi6PX24XRYTXQX>iE&|CuL>%O1TnKYH|sm8P;5G0JT{9s zI~kSN4Tab!o$^Y2c~!|?)D>IvcsG+Y9q=@$FQhYSEsY_svpOGpi5Ac?B@$vp>{n*C z3(~SlF78_wV^Ru(SyOFypr{cErzlBlmzW7ZRL`OXj)9u636RkMycoTx9bkV&3TDNK z4-W=Qq;m-V;Jj97S@33rr$tD=4sjWZa6T9CiZqjxy|YapV1#gkQ1r(Vm5q1E?PQrz81{iB$&aWtg!}bB!)bLDyH+oK~yIG&I%3x+cZV$oPGSSwI!ou7X%~9C*B69qQ_#Z7?cGL95f-?%`kEZ zhQrO*%?1Laa8;V1Dqp@$9FMK+49c8B`s!mD1=Dzzi>Zm@6rv-5|)Y zES1K<^0o4WwvHhe=If#S6wT07RrNdE$7n$jSQ`4=F%*wZS^ZA`8d4Uv;so(P(m4lN zxz=P{tls)}WrK(3rjp|7OC~X;6F!2J;|7CxStVwn+MW7N4&fwQg2FhFvmA5Md@3U2 zp3u>7L@l^{w{MAkS?C6F+mB?JwNZjiaw`-+Vv9ON5xIVska$g1eyo}SqqF+rnNvyX zvfxj{bHcxdm{RS>5b)ZERFl6;wWUK%l!xT=(dezl6s$J#%J z=ec&<<8ad0Y1CMa-PpEm+cp~8Y;4;}!^TY-+qP}|@2<6;{adU1d3X1-kN3m<^*pZo znDZQy=NK`!{z;>VoF6*d892WRA5`IrUwFvbt5V3-;$4r1$C~5~;B9T3WMdJ3?%-I; zBkt+vIfIaiM({`1&RAWGu(pQS>M|8^x$|GG;dV`cDN*i%ry3~%UMVgoO+ZA_`;mNs zve8Rl9SO7?1tf3Myart+nV-@m`*~V_qt$I+550HYz=jmuIVy>>YLFFJxpA*}3P&Fvb?G%qbj0VLXA9hgurANp795jsrur$-mAi z)ShtV=T-i7UtKwFSKiEZFDo4?voFFVWm=Pz-k|Xt3d2bvn{$;Pjrr#OwajoVVd&6N z^?*`Di}B}-W5-3A9^)g~__>2kl0-AcxQQGayR@Xm2Qb{e`Z4J`Gd|=tVt%rQB=TeG zE`Ew}MJ#N3pBkvHWmKb_Pew#blz5i|IYIj5bNcXMlqkdjkXVVPi?{*Aw%-#Y21Uhl zluNaD7+EnS-GtFLMtfH)?QK-n3*vprr!;WNRA_5!m{f&oM9*_gyVNG+SY=E4>reeK1HveF-3#9Fe+ig2@u!ntQ?1>-3ljelZnup(4`=v^AWWW)80+{%x zFum;m!Nh;j@&3co%6j&E_9hO0z<9y`tJfOk!5~v4W&}!<@x!KZ$&k`c3l6(j9S8i-rxU(B zwlWa>G8|xPe)*7#>W2Zge2|Wnu;Lj--)2Iya70&94a7x?4a42PyXZ3NDH44$awj=N zRAM)6c2JeI4r^MTL>7vS7bDu~tsfiN8Zsq?sfSX*EEpC$G|#@j4y(IIr#)NqdZyE{ z_(0X7RBJnB;kN562AdcBsE6$#LJn`q~%M>hPaSM!6xn4$MMY`6VOCe zs5pP1y3;RTFNLE~QaTBl#ily^0#q5eIq6Eg2zRR2}^ zkJn!&{wOiB9zQ9cO8}J5V*h_~v_Cxzz;{Z>g7SG!1^a!8UkI$Z(n(LD)_WrbY9**8 zswYLIL;@u8Tkymwg@(ePf)$zdfq=@YJQ&3=K_KYn`rFrY*b?TOTg^N=(U}Ovml8+M91*^~vVRG#i zXBe+h+8wQ~S6fbB&ivuxiG#Cpyf3`G6-}TzuU=z_!Y|)b0x_!_@=6bb!`KSU3&auG zo(uO+h+hwre#&j7NYPW>MU5wnpc#bd0V!a)BxXc(-To2N#m*JfI*HGOc{4>!CrVt0 zHXBjBI5Wt0Oe$Yo^ut;mPq05K0RsmiDQBdt#(H8AqHxfqN`5vt zrTt#4N@$O0y6|ZrVW~w(Js!|7{Bp6e#SLK1GmI~LFoYI8YcXPLs@J?5tqy$H$&oS<^4%q= zF9P-_0yMq%J6{W}yY0(M816gIEXI6w$X*noPtNcjgYy>8aUG{cY>yW~mSyz5yDuYQ{$BD|(*hIDd7)oL$Il^F+@!&we8m}WYa%ETb{r=4;A<`cb? zF*aV!0_9*+Z3A~;=-hNq=gs4HyKwUSI<>iRb)x@j%Uffth>&?w*bo`Tw-6p91Imn6 zXK2P^T73q5?*<-%kvLt&+O~8>f>LNRY|*&k3a0;I^2HJ9KSf z>=^MF0W|u=d!5h#~t~Frv$E+m)kA`A?2URc;o}WH#Gp9CEBV^c4@(Ht#DIW!~5y%?_;*fb^`&PFo6@4!(P%qzK2m-KSRfv z@!HA0kE@OykBa#=&1dwn9ChKMmiMa5!BN6Lq5&3^>DE=luXHB9+om7$3xB7mSVj<6 z^PpJW>Xb^mB!cwp;r7PWi#~g6o@B;?lx%gG(E7!K7hGwkwb*9yn5@O6S3x0S&doU8 z*9~5nif>QfpA}ABBzn^f-j0WaTj_yCMsn_cshZ04LR^UfftL{q2uS?@fQkR&fBr}G z{R0#;{$KSp2_qQ#mBnf&1fNN1DnB5-v{Zf8|3v?cz18C9gTGPtxp`SpWO&c-nN@eY zBa|3fb)bBuMBC(-Y^5psU^E4(EC~Fgm)KkHq$mt0 z&5{T6A#I4Npi#iL%06rfvn^H+miB%D8Bir;uuOep8I|RFyc?>9NHOueu|E$e0Ucr9 z#aB4t`5}Fu9V7AHg!#=~<3NhIV@iejhpbjv{%#x@UV0XUEqs$=3WGl;dUFBqg4sQ8 z5;-&-IkOD|T#D*@!vYnQ=Y4FoZ+mDI`Z!C(TDq~dB!Y$AfH zh~U1&>%qq1<|GcYQ*QH#2Qx8rdqAex;^uK1!y}z}KQ8Pv28|ywGJu>JeB;7dj9qva zs-Tfk@NHgWZ0pQL?;h=mw^FY}RV}WPL*+zyaCiUSp~FtqoWnZ1QT_BCF^`8VeNF|M zp;AmXuMn{^BF7hG+*5g@{s%3{rhau86~!oRX%%Vf1`LKpZG{o0Vq~)y`2|OkkO~%9 zDOn4bM#4d27v}ler3(a~IaWxaj6;G1_tbD8SCjF^nJ7Nhr{WjgR!512=GjaQo7M(+ zYU$F?!B6&F=^Gy*ZqE2tTjxNlp_sdV$%LVbbU_FKEewA^lJeW#mERRRvi3%XKS_K3 zddsBn;}1rPBT8nP@gd>v<*nS9_xCaHtl>1+0Iz6@6U$QploYjC^RIU_#5~9!_XD%R zf26D|$OYPmvia70je&`is7>jMo9(AT@QEo#DIoqDC}wd{#K#2dms=j;bdIG$hH|Kx zJ=>o{8G&XXL~Qn9g#NFfjU;nB`6f|=B%{44vy!EVv}D-yfqqp^s+ z7ChK@=)7%Y=Bzb-1w-;9T6EB!QZS)WUQ^Yf`C?GHD% z6B5UGL)D#6@^wD>`a)=)q_#*!D6@eY*hVz_MZv<|xZTb$VpW~3U`_aNfmfKBBI2dk zBw^n$&RaqC`IQgV+2}srby>IbAxD!WU`U)S@$b!vAU>bunA+U_7~Dc)YK6^e!CpD> zcWk0v#sYteU9a&^IpPk9N<&yPlR?v;tR;|XaA3{IdGvx>(xU?HLKI;io9Ks4Pwm*ukf$-vY`ZYVH7<2L-Zn_K`y8(~lsW=JocnHpe3v zd~e$r`?(;6sbCG+P?)^#wsQAaCGhvaUS4My9LdXdBe>1F1~pFLSr8D`C=J z6d2qlk3wrF`@7bTV~yfU)cO-9qu6qkZpHST1{1gX2Fskk#KkYTDqYOMow@d<7$83s zW(auSpJW(kHK05kI&FPoU^vB0s}OBigUmP8J}=vxI+p*bc^e z6#KI+}ZzAR~ps`n#77v zYcMihN4D7-Gx#wtH02sDQ896a)fcI{ou&Bku-zeY7(Rrp~5Xlkl4FN%-?hy zrieciKURTboaROr%`AZFlR`U6@)fEN+461p3`AyZm|X7!uSD}?wAn?xevD@d&eAiv zvo-1b%IZnu0=}JJO8Q;VbvhSlXs?9_oW;lFdoAoN_bMHDgjm$4CWY?v;iWA2mpexo z)NXvL_rj#mv1)!RMn>M%K~PyiOIBpfeu1)JfxO>3at$EzuufdpB^@8Y-&t%!%V)1M zv*`0r?>XF()${pCMF>`MU_DBrDiS zPe^23z6Mk@Z#&^zA&s(Wep@FemLJ_@m!oAT%B)DgNYULedLv;8vFd91hdj6M`OzQkj05LZIo~A&I}RJ`!6_X3Oe1Tn7GuOl4DqT5`dUMWxg;+S(piCGk zgxCgd=qSWc-Y1`9^>9u5niM#KDO2%75qRx{p4gMm-TqNR){JV(ZgQM~$n{5F?h%5Y)R5rnrR}ibu4H`~ge-CYI+1r#fUlcywgFWzg##w6C`z*HeN38F_;? zDY8*JI(?}#pj{+1nA7B#0l^&%b5XIn z1Q3G|I*-4oxMx3sn1MLPJ^wRq?jsa;=GjW|p0z<#E(~A{{ zXj(8~7)f-|!~nUWTrh>2?(~X$0BgQpfLi}98$(I@(RoMjF(ag_wy4qi2bxdAvP1;X z1aO!%LasD<^d{Za4+q+vcKzi`j#||(Q7q-UrnX7#`zDalnc4@=)C{;4cN{Wu#KVl- z8Io36R2&z`~F^(gjoFIDa0m2shT=z+ry=oz+2lkDYyr_riVV!Cl_R!ll! zpeGYL;0N_11xC;#0%->6N)4Si{IIsBv~*6#tP8J!PPxvBQ!JP&E6star5f2ApYzSjwmJ zh6N779G8TPz)Clb2eomZX5x{v9Bv`t5Y`cd7j!^>yNZW%Ou=eE^Lm zF`LHsWKwX`5G<7y*kQSlre?%7No0w+$C!SvToSRLuYpP15x4bCf;g~~sFtfib7De2 z6rx+p_Q&lsQ*Q6dp7SReq3;w=5|*}QG5zQVFzeLDK!2{LzM>~ViiVOSD|97jGYeva zMm?6m*0I#g&E;Nfud$LdOD>GghNWQ{WRbn^$sliGDy;2Y>qiP|@EBjje^&^Bsc6skFXJEN_M5e7ZgV&*I@fNJ-?!7V;=sYY?sy3Zgr7p&EOrek2%~0zR-;>Pj+Vaz7W%zZ6Zq zBAVG+fO{}4X4IBIhelXNAm#tyYE&PR4o(R4AvAVdU&9ix#9fE9^8NG?J5pl>eX5|| z54A8CG_*8n(-9|eNZ*7Cw&oZ&86T60{LBv}=a6&m5UGv^SZPS2Wo>_+^x{;h?&dL* zDtK`JGF~z$bqE6;_w5|4tBu0!d}g7M{WC)5r7G%L50x zG?}L;o5>Z6(T?N~o?4PwS;|wu&q`X$v}b!$x-FJa9uX#069X_ME<^58-RllHWM@=@ z_an%r*giBHyfoNh6h?;)=0Vp< zXNO|I=!X_i@bdmgC&>c74Zx}9CSm0E_o*IWktUB0rR@q;W)UV-{SL%E$Ep~G$qEt7 z=?;Z$6l57)GSVzC_tgW>H-@n_ZABBYc5fu@LUOP#wFq)CU(%3l))cA7;d$J+okO=^ zVh0oJR@uSngq5BaK+G_-#-`9Fia`r)^)<0Y7n%AH8z#K$D4tbE4<Re>`i^n(hsUCv3+j0yk^hcY;cp4&7yRQWlEp2iQOh?wh#3* zh`h4wrzou;Mz_31nS&{@FV(k6Io^fbnh_9Y7aXSMHdWv%3TmPv{2U#%$m|t-WU=H3 z?&XkjJ!+QNe4>w}h>9tdGtm2JN+5W`>iI&oi`G^XCq8oyG`EKi+K3#_`#+o)K7#w& z(xUQLUEpD7jQyyPd0JtS(q>!jD2!rJ9N?mO53^Nd`nVsBT_w@Gf<2ui)cMZ)J^@w_5y_&*`ni=vgEQ{1I_t%A-RC z47Csf75(3IOPDfHLDh;JgqFw9`vXMGj>2;>8|FY=23k3>p+aP+vx1YNgUio8>22)L zP;q*oKHEl;md!bKga}h{s-hfMp7u`Nv8q=kO>jLA_176ThD?$zJT2C#bcw4hTHc7w zg}({#>n%m8P8oeB449Ot1$(Th!k<4`_(cIq=U6H1r-aJSK=#u`m3Hhs)ekyeU ztkk|oNo9wDY=~DaL8{yv0A6tP2T9k`I5WB0kfPF)i@cS^`)p{MBr7hSrL#mbdP&H7 zv1U;*LqmOkFr4~98aQoCEn~&2JLoHNgW8|eDM5JO9TcHN3hIR@8#W!NOZ^fGRvZ!c z_NKdYTk`dEMQ1lOZ$(tI9mo&$Yy(ILmh?Wqw2v)TJ*4ZG+dpmEV@S}$+^iE~#?HQN zswrt4ef}Jk5%q`V(9B7})EE7wCR%vMUHQ)-m1jj0v2!wfQ0{!7DH6%OWXIk4`)Ai9 z4xmr()y2;|`wQ2!v+bWY4v%+EFo3%P_q2CGU5YBVlIg1M;@mPi@@&MfY+q2QlU|vw zq-X;&}zna){`61_oqTDky|5HH^mqOBXJjHc^%e3r}08?8UNPHGwJqkta8lYCLZ z%^)0!_4?%&0W9-h(EeLgHUN+dm{}UxTRE8g&pRBnzccthPWrbXFLYtzmICk}8UV;k z{^!U2@U1n`C;6-F_5fEm90_&C#>`E zWTp2%^}7lZ_-)E=B3z7J?1yF<`C=#tECVeg%}a{Exs=Sdg6qj|lZy~L<_=o$xsBP$ z$4VHj2X@GHn&Gq(jLBc|9 zi7{e7eTh=BSz9?4N)R0L<^(TY@;pEb^z z@zkJoxZ3di#W#O|xh>EFTp%0(A-`R#{_h_3-(BEOwEu_d-(ojFKSrNR5*dqPry7~Q zi&`x$Ut%%``r=eV2*y;>w2AD&^6gbVhm4Mtj(JaCBo{wTO|hP(ai6xCt~8EVZO49~ z)0~PlLQDzcXal)3_DiutlsZTUdrV$0T`ab?tgL2%@Oc8eD+3@c0rwpTIDc8}v81K*e+M$MH7hkw1v8|zT9 z>xYRuv^Z3p*4P0nSKNc{+I;&mtw(p{G197CHT~`Q8vQX+&2eHhw=S%UmYh?qy@2-0 z^?Po-Z`Z~lmg{3p$XuDxGbBq>xEX!MfLS`Wz=>L)ZUKzdZA%OJn?q`;oomtU44JcwG}JOH*3!l^wGt& zH;3P;C>MOAyM*uQrK!<1fb=z?=OwDg-8YsFCZH_ zar(Muw%%~96nTVkU}{PsfsnHfB;XOv?`;I6J4fD+S#R4Bq*VN}?75u6nc476KhBFC zCvjveYc=zW>j)|KT?Qw~2?&2AGN1RsM-)m5Cy156GVqJF$hHm3VlK--u(9-kUzK48 z^C3j;Sl-B3R>*gi>CKz4^G`8&!>`LTRUW((P%hlC31*t{{OQ zibp|frOnW{`PlYg=Ac1WNnKcmVw}obNUXfT2x(n?V|-+}WzojK26*6i{xmY*tI1NY zkpaUXvxM}rcrp>SfADsFcZB-sD)OJRprG^URPfz z?_yc^bcJtboMqn}PEH%K?x3ut=NN1n?Y-tW7FwI)iKTfedaS zfK&MboQnH*PW6wIBL1SXJkFMAf-oKnxVAbe^9w)w+Av zD7DKDy%%)TT++_yVvS#J%%(_NL-X$dQ~5xy1jkI zW42bVymQLQCNhWk1D_>a2o&ZX78Nc^Jb|%VsA!yS9y2q3Qu$3i^28(7zPAg5_KTQR zG*;M^@`D%EQ2c%H#+1s^hei-ASIA@E9dzlfBUvHV6vzD({A4NkJ(mm>Blys54I zV_*tU&vX@+yQ$naNTUtLn+P^OR>Raoc&&>YE0lqoM~-w&H!<%+6G5VYc7-?5>zW3L zor-@$0t4%d4;37)8#r@oY4Ljs#!hlMxRhvNPhoiTpp#447HSch3uS$b7Yg^(T>zuU z*5n+gb%vy`mMgrVYc$lgZ6rDaOXj3VCH-0q52aHczqKyoomnLEkrwz&d^)xCD6_d? z3fF{?3W3hj7(I!BN}WaSQoY~@OF>xOz>{aY*qX@Ta`un-+JQ92P7l?=1&f+I0u*}$ zBqLRAFbO})N(tw37|yf2wSVFcVLi`#u?+;`Kt)+GJ) z!-;)sjHoD(G-|QJnNA{CIy8ITVoKNF&VXk)!wgr@k2bJQ>6D9qpf@n%wllK7>IxQ% zc~I=C9LWn=sX3eOyKkg&&Rrbf{ZJMbvuoB)&!HZ4h+8m3>H9M$P!BJ$h3ikb%Y z%X@bT;>qY_-N*v3=n@h*fu+`MVSEnX1~*)HkiNbu5Ln4H0dCGu?F6;zQw4b{OOB=! zS0%XtP}EHA?ug6P$KXHXb?1c`5KQ*NXTw1zzG<9kW&boGHrH;?($wsNH7xDFZt5AP zRzBmg)TZMT-=JtpYd2k6&bbXr!$>Xvxn_FhiKPod;=_v?@rqFy9UrQdMWpi&FYNs6 z{y1Lc6n{eDi5+ z%++grYY3z!feoGUx>+jmQA%v$&RO$o^RCUCDFNqBNq}OP&D6eY&7|F}TOv0PSE0iF zmUDwDZIW41rOZ|_6k9kS;lhZuEFvfR+fw#AIcit3QZxP;j?K^Uw56~QnzQS8>j$xmFNunf0X)VeC7!(A+ zAkO~?gZ{gBMapYg04RYx=c-iq1+3!Jy?rEN#cpJa!|f7+<;7JqW+#=3IBvL)F}L1U z8}f;yp{;cs^^-GJQdZ!N{84?K5@VPKgO+FYBs`8%NqJG^4&v5y-ro?4DK4pfSSLM| zHDyfXHL(1aUH(3+Jc2rfcW0A=cFM7ECpfASnFS?z!23;1L!)AQgPl!8MNXIWYJtiZ zgDNL~G*%E7%XuFq704N8K#_7vb4)mQR%zRqXnEWw| zls2`Pc}~v}o~l~2IQXSxY+7ml?X}s3tsXCD5bvC$9pkSJ}*S-W`CDj@H193h8h_=11{623fpP3)%#_ zhq8H}`EMzCzI6o`ev~Q<-%fb`WiJ2sxcKpRPGDwjXyp1oM#bMMOZ|Dozm17L5ssBP z0Kh8&w6uRK!~C~%L==UjjZ6R<2+l?_)_-lMD0WE$+!4?b5WeQ+9V}Gbe1~eks7@wt zCQBEbsoRcAYJIHb;)3Hx_}b2ZwUv(|>tJuZHtca_>|$P$WFMt_tXT|JO1!u{1dSJ= z#SI~t!=M?y7D+Yc(Vklxd2=pNnNL=b2~*N=G5J9_+(wuQKybJ4(AwNA7(^V+)Pazm zLyGP7LVCQI5a{lSmoCa7vZkkf;(6Dn6`n?Nlkb$O@Rql=g^Mjv%WE3058hl!%`UP7 ztWs-9w*L)_pO?>hc%plmP>A{-3@j3Cdnf`U6LKF^o({XJ%1#0 zDZNL)P7o5@tCF@q%FUL#tVPfi+b<3tB0Iua2#xGL{V}4yS4q z-M-*wDB96Say$so@O6{qk!Lq3&XCQhHdPrRlM7rPkraG^q9=wf;S_XS^IlJ9SKClD zNcQp|@c(F?wf{`M+%>UE9I;61(d1E*IQ`7d9bm;|Ii}bBwtjSrXB6c=VJ&f!Ywd8Y zbBy?@^(9uaax+i6UJLzYWOWv4aO~**^p*to8_&eig{3Dd>BVuVee1}?nkNf_X=k#q zNt1gC;PuULfcZ$MtJ1tCMZkws%S`uQspIeiji{V{ma_mP{%ynZZ=SE9XJsU5Wc`nZ zwUmP&fKTd*(z)=1BjYO&?R}Roh9bD$VrF^>r9457Sg{fIn}@T}2UZI*W#tJo+1@ zcH>*vBYUQx8CElGH}Pj%OjhJpBh?%2k(VM$!mc_K+U~C_zBXz$>j)&yx=+DDORoB- zRcKPjq+?FP($%&m(T$zxqumG1Af37VV;p&FANj=39|osG8n0NCbL9`_>$SVshA(D zOblkW7;GfKmlv<=m(%E(TnP1bkoe+ovCA&ix%lmARQfUelOT6}sF%yx>J`Tas>~W# zz5}WdhX|8mg^^uVO0Fd;P)(9%SX@dH{;{nqelw8H1wSyqK`LE&iXK=M`esEtCJ{3_ zD4j?w=z6_)CEqHDsBu~B_V!Q5(oncn+6b9+89596ZQnibjMX6K6iu3`7?XBB)7psP zs3-_9b`}w>WY1k?L&Rg}oIoIdv(j28mYkRlLCVZkC59w5v4ECp%<2U;Y?ME&Su8D40`} z6jpC55|IHktUd`SI+%E_R`t@{m$fLd_cSTm?@2Wvc1`UQ6V_q49d0zjKB(6zVK8>V z?Y3BGq>3p?Xe6h8$Y)S8MtaRw2KH=7rCw-5B+@N697HxB<1Z42RB}jBgM>M^D~s>H zx?SPcM6#2B=kA>LA3IjZi@4HcSuQLfDwFVVx!zz5n4;mdx?N^KXEcgl`Zy?;S0J!) z)}t}Je~z}VNR0G(pv$oZf|%Kg>5c1B{vO+}o-JSj|GDXMF_dmzfxw(}UC-p1E#Ar) zY@{xj9Q-gO6h%b-QI-;n6fXQn+#KXyd$m0iHYN&FPJwW}tHiwEpPz8fC&6Om0vws4 zH7|f)gaJ~V74?J>ktAnt&oj0cgH0A^zl;r=*c=#sDx!J*Z_3}l-4P{Qz>tpL#>v|7 zueQpclWV|~ZVAx;Kca*@jss771a4>5fTIeoR6E3Wra(_?Z1|o)`C~95`;B`@EIt>< z50wr!*4=Y^OCkILobufsWyV~B&G#?3Sc`0(ZepfAU@sFgT#Hx*l2hz>>nzrC8r$L@ z>tN6$47`pmI|$$vmo<9}k_f4=)LURRvnan0hOX5*@@6YimJL`nO%}tf~kq_&JuV%~oK?cCJ z;t1HvZY2SA#p4JKpj-msaNYE>`4U(1R}hp*L0kr=f==;oL#RYulv)iAkmzWQ^=*`5 zweUs;1-c}{&c&Q%mucCA*YF^t*36Bj;RnQWCYkAl3J%I`Y^kaGQ%$Z<-S>B3pXuR# zymt=Czf>pQYbuC~UyElMJ=!@GVeXWuQnasjtM$H_b-cBR<*vk?96P6JO{O++F-xM! zD!8rRALI`DaI7-uA)~ZZWrQvoA$cS*99@Pz*SzU3@?>)Ji#pnq9YYx-z|5ThIQ*?T z+TYClQ%Lf!*!E{*R_@17mg2T2Kz{>F_7mPW;^GnD5=BM;KZ>aZb79J)f;XuN-`GoKYL22fiVp9{#&os6rbJv3`8dUv&o-F3kIu1|Fhhhal zPc~Q@a|ADPo?- zcnTM}ym!K_ObS28{j9VXZ%PldMaS-X%EaJ78lA*GXI%7^th)5Ee7WPH4^gygn1l=x z^KxPA#nGfMYZ>6e@%``8{6BJZ1t)z6M|*&X#UD}WABo1FCi&TN0z*tj zSVzJw3F!R@9lDqq10`WAW@*k*0C{odgoH$9W%iXVEhS?iV`b7-;3Fu(N2JP6%h{S@ zsq50;rPS~vXfOQR3K&mS(IguA&0P!55_%Iv0_=bDd~d)Yo2(|LFH zE%72WbfwJk=v9WOHFv_@mPE*^B;%3tbk>#(QfZlPIkmKeD?vsICLfhPH4D?os>Y41 zE=2}`!JW@R!sIlF;@5!!HhhV#Qq3m){<%Wz1%AiznWw8*30bza^mP&=OErdS! zHtYsFYL@h$&7!2U83`AFeXRlZ{cSD(x0@yj7=kI9>RJC2PNi%BLKFZ#BGtvf9O`Ev z8X=7WB}^=T`+2C8&B=(k1jZeKkT>q&Drp1$EhM(ltE)O4Xh~yMVmfDv_=q@+h3U<7 z<^EA=sFLe|S$jFXRW$w)7y}&74J1H1O(AEoHBO$lQzur+W+oDUtE8D6AKaJbR|)d8 zjXnU73+0M0Gjzbg&dZ47FnCRGi+Y~EOp!0Qzw4?IM_mx@JP&0aWM;V#bT1KS8a)_x zRCvh7(LuVR&Z(t(p!=z=VcvqEkY(1>KI(bS~>>dyU&*8@p+^Ga=jR#+sLlPQ&K~7?F1A z&MCO9>NlVdHa&dJTZ>orSQ_5#`d=YwyikOgj6WfgDO)H=nu7$ncZ$xR_Wm*?Z-1Y= zG6XPaD8Qiq33N)^SpO@L{1Z9>1hYS5(uikad`-LL)VOm+c1yoY2yV@N5tuSV5Hk? zWb^2)Dt-P8HgjB~=CtKV`eG%I9jHl+ExjNsYJ z#X!Af^$w%@bVtz1(IsJ51CZAJz1GaH;emsQ^opvo_DyG4d>Z0%{4=Zw#A`9UsJu>+eyiE~y z*NE6GX7ry;)@Cl>Kd!f&f%}aFB@N3>`JP-Iv6C;~=mW3g|-5#Vo3uP*Vovr`K zS6)|-JnIj?auM$ZdL#Z^qWA#_t^Y~0hQq}&;=c_`@Db|vtpDH352W6@jqgIP5!U}N!@ zqPB<6L0`r04dzbwcfoYze3vVDmpBQZF)hA)lusebrXESN>6ebFs`m(xSd$1>a^i&_POy6$~ahhhjaE^Aa0%&zPH=hg`2*j%M^As>@_XiI_tnwZSK*j z25gyf!foQW_~O+)P|Y*kq1Xcyd*q1N)PMBUs$a^iOC;&fCOh)2HO9Gkoc%IzN;!YV zngbX}1<=0#t%&yD5cy~B^GC4#^ZF|Mnc6=6k=m9#0^@)el_7x568yl1w z#YYBx8j8CjZKgV-R`F8yy+IbNtAzO4yymnqkmMdDb8mzvWFYyHZ`+_ch8B4c3n4h! zFU(F{{ryoujzw@vsSEmE?a?W*b%OYJbB(O5qa=JCBwLYlc^;om~M>OVdrs? zRv|mD)CIA3y42)hTfTmU__DXte5hdqq}65mKDkheS%|0QOD zxw9`oG{C7KNYrwo)3*T;YJL*>3QN9(y`3&n_=;ZHx5j6~u5%2noBD$epjP%IXky|Dwhj zI(XOW%;CeF4--)0Ed6C&QMKWCAQMZR3`{^C1gn3fBTSr_ zgsvPx2nc8t?Zn-9ShGe9ilKBBE^E^J&8~CS$8Ao#LDUggm0+%~T$^;~EcX^waRL7&^mM!U|2Cw=np z%&m=V9#PVs355hn_q^kaSMbk9Ms}Y14|{2erYHJV1@RV!x$Cn?&83Cc?;+cLjYq+{ z#|NeW9nr&M=cn~wkbslR`Q{K{-erJ!f2-pD4%T0z&9u6yeEwtr_BLeZsK1ISnXfg9uC5b(C$VEWvkZcQvqNtG9FydyDw-5)m(z( zE_3N)p~ejA4w;0WZHB|f{v8MD5FZ6p9pd}Y@K>b#fw;LF*G)DsmfBJYc5!ed%xDl| zE`DP+wRoBad#EAIsxKAz14EM?rt!#ay<;ML!CP9xh;N6m?vreCxq|}02KSD@9Pr}; zTHOrGKz-gF8?ft#cD)H+Pc68$`bDo=!QIR`6`l0Khm4v&0z#~V$G$C<6?1%5B@WWf zMiO0LdRF-w(gK*+Gpsb;)8Hp=W;E797F+|L>te6M8YuExt1bV4Em7;n<}bJ+1cIRn zxum%enDbcHdOmR67surOJ}`UiPxIO#GlVUCF}N+~$*6sX02B7m!`R*~L6dvG-n4oe zc_8#?ki^NgO#0>g1AE#qsf$?Z@LhrjqqYr8gK^l`ZB%F>2Dh-e5x+3LVO)n4MaVkq zAJt1DRsT%vZ=^YuzX6$BFYzB zQ)OaO74hMhsbfKS+Xm+fCc-F+b2!RVUI>v&2@T1yw}*vGTvpFWNX_}e*aP?>IP@H} zhPHRuT?0u-S#(#IpFJ-%!mEandFF!3y()INDt;JmxsKprXt;3TLeK@Jyu!Yuclx*CP7O)rj z7Y=!lN$BROASXSgFT*4Ztb(D^P|PPHOM~&V4tI-Wf$fHkxTw@_-7NAOaH|oEp;_6| zHuJcBaGvGnB427j9XuY3S*|aR4Fbb50uTn!KOe4btgfv)xNMCs;j<6Wh6ITQeAqw? zzqy-v5#WT*rGeVmP{Qsz+~fSLNxKF0tdcQ?Ru}AwN~?Z~^U8G0qEl8e=|LQaRDlEL zRJUPsn|1VZY{st%iEam^zV9rnm)Ca6TwOnAA!*S-J?NI67B1aQa1P*=7NpS8KtH>Q=S5qp+E{*PGOUlz*yv2xOY3DW& zvz!Ep0Ev#f*oh`PavV%K{sf2gImVb{__&4oQYxa5*;lvfkgOt3o$QG0pHt@*N;>mY?@z*OH`?aS7R-|1ePIgw`rrVau zF-9GqMla<>8d-aN6{f6QY+B0P6l+XFBf|GiAuES8zJE{Nm4L98has)oig8IA^_4^X zi5&M*K&p%|p7yg%+nR--SQ!r5DryPa&nGxWAO|hQU(E~pY*2TQ!4#Meql4r0$I8J^ zLYYmH1#~$dfzVoc3NTW1kLB%;(wooEwh2-FXBhokrR)!RO^xiv+R$g!(Smn87oIL0 z8<~p4D&IIW8&|qJLj8qA_D;Y|q~&u(6v-1+;%=Fs!64y*i(1vZ7{rg5XUt;S`qYnj zE}ec1!ni^q4@#2pmlmqKjn+pDjBRA8t4hG4_^qZfEy}&OdW4(PS?;D= zodI{F#+nIM=4o*89upsgvcGvfK-^zMkp^4Kx;FRXxzD4)qGdD_X&sd@DJ$2b6qC%P z7MLcqFq1MS7_O0S9-^^2+`o8dDht@ffvgp4eIg{^a(m*&K7E!0U^@?*X>Q5Pf8J_oxI%brfa2opdUJd{S+nHnSc|h_JrE7i^puq-TA~yW z{o%}2ssdvV&9Jm(=>O|Avb`4f(~~feV(^Qz|HPDe7FlA>w8RfVmqv2 zL7nk&4!%<)N;t+>AShQ+ak;ws|O8OQO=Ug{4_AW0_XiV@DOpi zVXPN0XAS{~`G0~%{4vJJ*ncxKG5uE^Qna!FkXi4SI(CJLBqR+dAq=Vw+tw4Rc{aqf z29a{KH!I2p5@pn6%p@OP@%m)aFh=>Z36xG7BA5LY^J@VVZ^YuZ z1JYc>hoYYMp@5BThX*-@Xfwx5&UCt~U;z(Ri>sK1>O#wT4=_zKO zzM79t?AkLCgV*cH+I2}p-p-YG%|^iHa`y#^AtR}&Y=>`#oUZ}-HxtI@bpw5N%5b1D zTruH28eeWK7d4h|KlN#JD-a-R*0tY{=(Z92B{Wv?kEMy&w%iIMb4!90ay5Y|Wb| zw>0|15i-&2OM6I}&ZWf;wN8rYEOWsu$cMyie`2N^lK}J&9@oa_?1Rr z1R7;B1Cx&MRaFynNUn2M8NYt`nYfIKm?(T4kf(0$wDDe;N9ekt>HA!!1?EK3XGI*+)k-9r2%X6t>~$4*TGDb6kkM|uRVPpcO-J)i0;w;c{a`aOkk)V zfo$#x*z{EWx?9V1YknaX2@sP5(8w)8k^Epa2^RD$*1@XK(7?`CMuzc(uQKtt$8@>_7XPjS_b8|ZYK z>EWDMIC)h!Z9z#ehSJbk8kki(2Z$2xgIgzca);w(zcy+?;2d(aJNtV|5#me@BYq_- z$JT>RuE2$KVZ>tZ`o_Aiev`jE;C@B={M2m~3II1TLs1^e?b=pWUR>DsJkr@?to_Y} zmhEWDsenDpsWhvQU4x4!Nu zJc?%fp+|R&!i2mrxHX9_zwKE$IyI!b>$R|uh9qnZ=3lu~lnjR~z`oaS(p;smR+u_% zNq3d2eZ~xw_DdXw9QIx%1YH&UN#7|)ma9}^!$9FuFZxXeo=ND-3A#c#Q^P$U?;@}F z>KQoMoJ7t2-vJG0cMnK+z|ax|7+U_TboD=5R3klm1Jge)$lnMFnLqZsR8)5vNg;WC zCCJG2A#^P_{O0zZtkD6Puu_-{jUUl-(b05Lwqce>E8Y(dVRpe3esyJ$ODHCWpCiDm zA}4r&hw~97qw?C7M+FYCiJ~Q3` zN5dyj3ZVEoWMdP^h(BZKk@l_y@Db_Al@5beimtvapWl}svil!}ts?~~q> zcq#ykF%Pk|u;>GMzJx*+z$W59?EuW+upg$Ixj~Kkqa1TmfdHerQm=VA2Ch=1@Di!x zw3mk}=KG!#fAPc+EC0qP^$4k)*<`y!#&oGbt5~WmFKf>M&GN;d2T$khtbOxt-CCO_ zHdxi%L!_NTupA%RlTa-uJQMBEZCisc$4>a39iP~|nlzN{h_RXki4+;T}D};9GWi?86HERM3!HlpqE1(@Bz|f6pJ+e7QFVa1wtD`_;=4 z?ZE_09>Rdh1EgB67`-cb>eCA zRhhA)@dO$)s|GD-(S;-rJR@c}^cxYKz^_#G?Y(r-k&ok6ji7S2W;&meETK;ey z7STmiO@%IX;oB>aMh=F;+tS6BW<_vjgI4i8p^EeuSgtXIL5tLWS*+YNQ=4W+2k`|9 z;zw+&6FaKWY@(1f+#!#I5E?W&SbX)BeNZ0U zW9CaER&$sfKk2gNCCv<8GSo?9ga|6ua_TqXL}MS3M|r;z?+|6y zLbtSIuXceyNfc<>jCP7vnG>S^!RWm6!VD58<}6I62uyE^=?%?>WgXNVufx=}EJ4uD zCOfpFV;;d%aCl>zPS`qLCLdh?;Qhnp3i($`+D)s!7LrCTVcCP^14hO)wt5(f5arOf zzB4dgdQ|+OrZ(*Qb5z%&1yqyV{p=1`rkcFf?E8b)*UNaN!^IpG-@=%k1O{4$+(U~z z5y2-A{+gFZ_x?*nby1|pqF+RTo5HxM19C(u!NJKk zJFY#kT;?ol5YqeIM4ai&hhlqw6_c(b`ouI6Ar#}g1$836ie0WBa8qn`x(QoC;>e(-@V8mUI1^ zN#9IwjYmjr?Vc>x8}*^al$m+)UHgFSYPB((t*NqVvJoZ|sn{(I-dCO{C%(S;cw}6jz#Y_hrOMBXV<-H`uKpT znzHBv-Wj=~n5BeuG|2?IZ%KKRw%oD-NN~mh&N0#Ocv_7f7h~DYz<8#+@U5{A@8~%a zo~!)WqL%tHmn%OlME#2xbAh@}neLRa(UgyK8M+kgWrA7?Le(n%e zm!PX`)z8(;br~Xuace%#CmC-|mGn%?&`NhpH=GQHX0K~$No#a&%sRGiHo6;CM|Clq zX;WMweZ^C7ez-pOmFDL-QyT&y{2tg<#2M7pZkiI!F!C}G>9DYk%hJ=xW62gr_2g*^ zZH6O!SnglYj91XAhkwF4XB5U2C#gE8i7km5dGws=09C0x17-9{g-^YdyV(N8HaDpJ?WEescsz&3~h<4AI$QHy&Cmu$$? zGiDokq$<7y1Ue*)UrCR^i^`Qx~-27aFoiegr-iygW8nC^hH%s`NhtputlAVN(O&s+< z5RWGlmgp-qx_%;^oKk~>p_;G;0Wrp%%zB5)sK}frb;&jsyn@gm9G;gPFGvk6;7~_-yo3e1-YJd=q=0WPo6=Sd(qXgfxt3QL{$3 zC#@#XcFx+uopn&IibNX{&x0(^sN@SD2W2;>2piYNo|)FpaPhBzHg-C$`6`&8-YSHr z`in-9A7|Y_H>;-ZTLNGB?~tWUya9$oU%K7~TL^Yu)^$W+KJY${C&~H@4@10dZPzVk z?!Hu|xycqq5~YbXB?KPIqIeaKC3#?btizcg=SBrhcFzws@#g+bCJ7%tiD?IT{ssUe zCi_1)EJ;Nfsec`ojPV~&VA8+6bJqn4NwDKAc=k)3iWKt*Y~huZgd@1$O_Q4%I!Foj z0fF5HmUH>!UB2Ajx5kGToiwgb+K3`iwQJdhxap^690EM&0hn-_lRgHqGh{ojIAKIYmSr7bOB5fwsF zMHc7seKi8wYwEL142%!xhmeWOZATdX(`~rD20nbdoEmxSqF@PmiXs%(87t~7VqOj2 zIgamYJKrrW{2CMRzMgqhbBjp>wJ11lKrKzhWPXXK45y;S>gqK;UJgr-T6%})V^3@)D1 z&m{^3qFrmGmBLv@PqYn%cUJQi1$jRm{R9~lHT6=L3OOh}^G7)U-IWo@8M&3Wa-v)@ zbDv-nMAjZ>wnc}lo z1NGr1)OuI|wX%haaDJlrN_9fHzkTC}fQc5jsj)WoU7{|@DtKK!lC~~Hlio|fHPl}b zv6Nant0cfN|6VBkuS?DUG4}sk$MDyw|36gSU=`5ks}UUwy|9%U$s8eB(5uB(H1+!< zj`BpuJu&9>hN=;{V6Xv&c=*rX9#pIA2!H0y7)czY3*gokR3V)809k1YBm8;{eGsRZ zyXT>Q?T0gusGd2_G%?)E>b^c$jx#8)p4^p}KuVV3&Vrx~10!3c(u1*)V$Xs&!ob=k zIut%2qbgryRopXu4p}Z{L1BCpe#aPfcKfS*;82 zCSf}*f;ugTZ;ByAG7Ww~-UqZS*a+1s96ZTHBgk)iEobh3uc1~uoeH#XkY}(ZNDb12 zP$v}W6-EEFFRF5}6>O$^%47&DcqXdhclU|LTHm{H3w)p+g`AY{IKW0ooUAC2A)XYX z>X9rAmjemvD!ck(_b0sC-S+Kf!nj0IX0;^A@Wj-62T+%$*I2{aU6=R+OwPr78%NfM zX5nK+#~lb)1Z{Q7Qj1wOEk4O3+sz7Xy9qo$$y7_luew-c0)| z-N(|u<2>3C_5ARF+GGka_5CLY{-+V7q~c$SRF<-Y&6)^e_n8W8reLXJae74-s68%_ z6F^Q|btjK9n2seMIilt6VkSoaw8hz=*-bpyWB|#;&Uv-e5)^tV?4Rq1EJ77|DL1UX z->Uqpn=r6UbC=YUT-ccdtH>>{G3aVnE-)=tjJ!}$d0BDfXG8cXPSN1ONrUGtY?@Ua z%}=)>Y-(9myOcM&91^d)2Z81qN{NDt+i{q@&y6%weXve8nOQ#ts%1-1-qk7&m2P}u z@o%N_W>S~Jy_JSU#Ay{+ekB}!6pCV%lukMBo_;&X?)G5ycd_M9C(@ho)q;{h2o#M= zf?RI5_>?9jsf!8;MZqlKkF`i;g!M4bCvsjX%t3=W`n?)9A_5&Vm9?PIsb-I0 zvJ(Yh%u9+tekrRMj?9vpOTb5rXRBYuoAvm}@dwJrhwU|fwt^m!$DHZ zDk`rD;_1V2_znk7nv}bMTcxS~ScCgWs0#*D11R z9ROON{B?CHt&c}uX2~0#%aWaD5CN392)i!vlb{{Nk?%D0Il;kwT`tXA?w`Dc@!&l; z);dT)MWvZR)X+r{-kb~UJenNf!Yi3TS{`lCcw1SRfThy<+`f@M2;c}Et&YZc!9k(w za#O~pG;V$ilo$5^zU{X@xm481<0)P6INP{67S@1EF9rWhcIo$F^kz#w*5t33ZlO*e zOfr-|4vATzS3jj&B`hb)*5Sd3{X1&g!I)a()r3ys~|dNoO3&RR3EtLavAits>SAIE{w8H?!}Q072JHB<-X zgS?Tz)C%O?+Cy#NQ6|7Z$LaWrp_^B^;Nx#gg`^8>r-^{lTKx}8>%TiFNi#ZR zx48IQ4(4grM$x*KlXJjxG^^vI&|8rkcnGd#tWP05jq($iR28eL5K}iw_9RY|MT$4xYmaz?0K~VyIN64eUP|zjlW3Iu#}2BZf&WpqOA?zIiJlIq$aM`$V6?l zjCkeYMEt}&whm3y>m{(b!YLkC97lDbVPuO0sZcw`7rul{r)M^zu7aocH=2Vet1EK4 zHVFAsje@r?ImElLK0#dFkJQJfOYY>;{aV`LrS8DhMBtR4O!c8meKt7WEO~NETpt|M zV9{cgn zVNLl-k`%ZTcUq0ldGD{<30mr)QpuQ2xx(~WxkZKv`iW%1{A=15VyCEw(MI>rIMB;q z!KasiQK*8Z)urUn*%U!Y&samcU1Q)XZ9JYNnoErDNM3+`k~%z0^8D?*`C{RVkqi#p**)Li#oO~4L zDD$PXvdR(D_OpBC+CtUTF9$|$$?t~n3HOEB3&Vp|%t6dZui$XA!}Ec7F5k{3F@9A) z+&e$+E_VbA6sHA9auI%K6q`o0!RWf!EhQM@oM^#&oDPGtSKv?aL~}#WP57Q)0fe0$ zVw=DOXKY!7idM8X<)%CVJ5`@IPIYD@%2F1c^F-RSM3#tgswdwnr_-B^F(Nc8c;*$d z?>5LsCpD*RGy;lqFcYjVRnY(ugm zZECnd`02B=)7oxAsvntP6l?aiq>@3YX8z0KH_<1pX&8k^M>G&GKBd9*=0x|6+o{jV z@fPAu4zXcJVhZfsR7!~|3`1HxFcHgFNvw_iHwM!Q0_5^2PXlAuMjl(BeOnV@UuygZ z2?qM|Q-)5y#=&0oy!Ny|H)euGh#-}O#8HP-)VPe{>)<6ju+?pPb$&dVwW)6|p{$*) z-8naTo@1ejwADJJB`&0I`h!uWi3u@TQ{n)BiWhP{ZfAi&i6gsUNx18qTM9?5Rq1fZ zxEW%>fp2s59jsGND4N*q!z`P%*}}d$i9}f; zRa^v;kMv`%OAP`_je->jxUvo6R#!P>;LC8MQWkW65F-2b^gSCN(T+L|L?!vqSZE(} zf*04EcbCDXwhzxQ*tQV*t$Xf1yxq3`-uvW5E9cyl|MBi|snEKCm$%YeTn_G9WL$t64-_bs^D^i$=y}ch?`7+Kg%yE;G&q2e1z*WtFGY zft{H<_Tw>?mlHpKx~Vf4C8K}Ku2MnDTEF^9s6_cfo8$9szC{;#smf}E_ZBr*%sI;e zb7tf)@K9_eWM>t@K4B9)7a4|%M~M`8LT%fH!Ny{?_z0{Ph>arEo#IzKFVR(jsTPvn z*&FN_>eo2z7id%U(vvpA0&wM$eF_8M5XiIAX;S?6D<-&I`x8h zFlh|^P%X=OnwXa ztHI@nQ;O>Fw4cKPnUa%#W=gh*C`!!ZnFLg{3hDV4Wgypp3?D;@mdNyrh=|p-!ArMI z%-}QNGxBBuTR6)&#XrvGI~+B5k~+y7Wt;L$nmN5mllj9Jg7xd+Wdh-y0av${|6yI? zTPSsCs;7k!k}G@E{po~2ut#LRHYzBM@GjKgZ83nZW7_Xb?bh{ru_#_ZNxHfg#=*dk z3JiXWa^An4g@RLdHfW^~+y{$=I;K1XTxZP2j6Y$T?i2N|QRL)M|1Und{b`Y8uHgUhZdej!4<6GNxKf?(3iCwsmG_*3om(>ydmp&qk>;I*_{SI~DiG*v5iZX9)`rW3}XWJQBJ&vDqM>{DK|V zr`W;~SJ5`n3k~L!H#UW?Y2&Ii+4VMOMP*E9D>7y0%iU# zCqiMn>gl2^Xzhx*AM#WOlm`P*0g$H&bLMTQ;2$L`A^vq;eU((3)}r=xK2`7`@JLY^{9flIS@~vRClDkZGGzt zf1*x23D8yq>CdGM#^H#yq4<4t6*_Fq=6cji;^N`Sb0tL%GYU?VezuFg#*i}K2Ss0v zYypxh1x?ZCNH|D3LQN0{h`{$X!{y5*zZEqmR8Nb0E?isskLuYwp`j=Ls68&~zwPDW z=$|>sswLAxyB>41C6)@d4q;z;e*dl&arON(EmgoGp1GUMsV#B(aO)me=9s+*KaBKeVCZziU~sgyW=PL4Sygf=F7GKSv>u6O8#k4UR^cjjD z^_KZ+45DDkv8DQr!0O&~&?P*oWJ>ykBv?Hz;q&NLyZY^Crw`aV)CYx>bz`USfppL* zAT3Z81dC7t(-H1b$-|9JH$_`uKKn}-zoecu4GP1I1o@^G_m>nYR=`Eqa!rj}&rDMs zBdhh~4ch`VC*z(IzDUhX=UW~TKTKRWh0GBhQ2#nq)R=HsXNskj;%qv$rsZj}$dOZiDB=PKiAQOJ0-qpWxuRYO(!-8uKJ*up2SKy?%@DsrDgvScHB) zaR$aI*z{hXe2m~D^oXFh2D8XxUIjl+ou4DKb8Cy}ypwZ0r}c437}@VF)yApP7_1a@ z*pOXjSUMz5ml!HxX0=vfOhgF@l+jzrD8h#GrIPE@&1cwViD|GzyGf6pA21x##bVxO zX1L#0IjR`n+gZmSXR6^yUC}=E)g4gO&wRBlmR+gYvT&^MI#}4G`s>S=tyPnb2KX== z5&j=6KmP;o`@i6yKSMyORL*SHSP(xhdv;@iGuGKhpETuJCAu?a9y}#p!kp!$xpVB_mL+6T2%Ab~TGz zqj;6_*>Iz7l*$@|V)SWt1%3!q{|13HN1md@%TdK6PEOEIXrT@3pR2#qebzPz>knVs zmE(}OIlc%pyi$rI>!ABQ6{MYOWeQF--)-l(>p(J>nI?R#jhQj8Glf;ALt;$|uy+kV zWWD*|x7MxCP^(jU|a?ZyamvZL4Pr!m=&Xtr9Gdmg-`M$50ADC$e~PxN{8A{ z^H|z6L797)EwOZNBRsraAI|7X&}S73Z!TV|zJ5?<7|99t$zY?of{BvP6^LE&EWeDZ ztpZF`{C(PNk!q&Z&*58@k}(Z03ry&?F|=`*TlNmCDy;$jX%&ioI2K(UYKLiAc50%N zVG<;CcKnbUL`Trg2CY|RJAz>uFlq6WH-3s%GA}5YLVo^2@1D@S_@lPn_RXHOzs_I0 z$20NhF7F7`rGbabyKKklWCZM=#@PEp=1fvR8!F?W&=JC%+RXhVAnD{=b4V$LmD^4B zuZ7w4ojE$*Lc@%DZ)lil77@vdt#%9U`SUqOR@&DiA3ysihoq9h%Qt)2d@dsoVo3G3 zb?OcLqNoe&;4DJV$i1lrytAIdsIr>AD%^aVuU@iEmYjpF6FM%iqKJ#1*(OAYP&<_} z@B<-Ky@D%fbo*5UQP}l_$c___4>q&Tj&$-SKQuG%^Mjc@Ckv1o>fjS0y;pQ(8Gj&) z*~E;A)48=k&TETR3>9G+YyVgDkv-cj88Ex-$l?on9I1@H&$yAfPrm?I@x!G)SNbov z&l@hm2CtX;?=K4(P>xfRHMBN|OZbyVDoY;v9-fCnIj6?b-z?uE68v*TkimywH8f>5 zO>+kZZ5#|NfPi2XtZz6zkML2OV49$FEgC5} zdsW&PkS#=HFXHaLl-u^p95-C%cUy@Dc2*m3*>mFZG8)u~nc`$RHz`3VzzZ15PtM@kZ5!9#zb!F4i6L!oGsd!XaJH=(c3fqGO`-=#}08?b<=UyRi)leu6)|x zafx?}wJ>CfCp#t>OVG7B6E)d#T;D?^obwA#hd-qcaLr45kPNu#!j!yiM9A=Hl;snZ z?3u3LmwvrL(6YbiX^=`3Ho~j_$h#;ft-AF{-4vC_?ihtL7?5e<&b5)QEsq3qlvtv{ zY@ob=7ZAhr_fnz$BKMbzTuD@l{rH+kLFq zx;S@ygZ0N*sD!G%X!v` z$W}J}R_N&(DGtN?6{aX-aIt2?4-B5;D0)0wYhz~LZC`B{6N#)@>3K;Ua*N=1Cahh^ zM6$~dK6%Kpvv%yCJPr77f6IOG-}lnt08A6V9j5+CxA_Nu|G)d9|I)?8P00gXRfewI z!n3Y{BLg9RFMg*YL0GW6>gz8jFOyQ3Q95I6ZqVqCkq2zncl6kNcv1w83x(@yjUHeb z1=HFI>@BvRbM_^v?T~FLe!>4*?5LL&;&M$0P|}SCF)YH=RPG=sD`Q0sFFaAAA1>?K zX>B{v3&`Mfy@yR$RU3NYMh8jEw2Tjqb*MNnmozsuSF2JzOV){_aMbHFVbEjrf`(Va zXV`o~KI^SP!n;V$=hR3;b>+YuZNDpJH^X+bP47MrHrFeKS;vXQ&pxHM`qIiP;zPbh z6TD$v6zuH5CZkY;1k*lcz;9uC71G3|&NVovwrtWjGrW0u{?+Z310f|M7j*tnFu)IPBtf#vFhSgYvFwaB*jza@b z3jc|u;t!pxj6Hz;`ctMP_b(}U4O@N4AW726obH7G7@A0)mc%LJ5QcEwR5O}}I7yos zyC6d_-JKKII zzvM(AGBTjd-XKtZ6=KPeC+hZtfyZb{6n5oyeF^0({c^`({v-C7&UKTm=AZ z1$H6@mPlc=OM5m+BjS@dq^_U_6GIX;@QOoPM@L-Pp)ql&I2>!2OEQBqlmvgd)OkFl_2HtM>Q*^C8X)8 z+eKm8I!x!GF$3cbQH5Q(*zs%q!FfTjr%C{Ock&8=M3ohHzh<#acD8ur|b*qS2Z{NbYYxGDN ziaxoI6Lj@`k)_+yb0sjRJ(2UB3@mx$amD@FrZF=@9vTut7>Y2!;r+GQ((Z$%tus4> ze|_TE^>H^(cO+)*dEjls6WB-Ch7JvV>DI8@bU=55It*5SD>$A`7wAiB$nN68sYnt4*c3S8yCXrHo{*UJ#8pm2loG; zkIugl=szEwKi1QQAK$~{+JO|uA!?zl8g%)E=L~01?X$#eKl9pV&i*zIawRSmZseRA zZ@X<}iA1Lson|TVjOygeP$RXgu(Feu&69u4&qz;F5C~*i<#^J~iA?|$1VxTQ>p!q7J(hm(g&G!^m>-FET7`f+Om_nf}=I8+12UOq@u9Z9JiX@v`xo@ zmd1Bhl^Q7mDnbu3x1{F)PB4eIjz!2YB#O|kOu^>Es3>(HD_>)E&}a6m9G^1nMr-?0 z_w`9J#0|S|kKvc#iWS49O9ipx+JMpOV|r}v2N$wqFub>_M8Q6LHeEjqog0n@9dC0JY>PmblpQh}4I{7yq9X5wP+#|A<~Z}tp^=;>1r z9A}RkxWAsr<^^wZ>Yt#}KPdx$x@!FuP5PHZ%o)HTMo(?JoHrL8y}}Pnb&1Ii{tt@@ zb<5GDeM6Dy4<5?POnn;v`!BKc9hZ@vSl~hjJa@`~L+*7Q!`5%@b;09`2tDP31AXe2=yR+$EsLwPw5Hw{GGgUvJGS*i2-`s42 zs|)G%H?v+12g~khP?r~W_$?JM?7zN~(zSP<@+O)LaqdmD7co2GJVh~L7oBXrkmbpegQNj8SToo7MS zf$SLs{fI2e&+4S!xn}YRpq?8jDS)NZdDlbZe&TTL@01@A^QOckVR#nBaj*LoH*q;j zM~Rt8&)ykdFzG!xH@v{u<;yzrJh6L7J25-hU^}cK2|vSKfC$(X=`inTVgd<^v)1x^ zt`%R|4-cWj&0hGMgob?x4M`4AWF`P8(?3(f{?_dMDFcgAko)Z>={;4$);FL&-*#mn zz%L6`$RMkMS8OIQ)JCk0+p!EUtMqo&;eag83RP8}zwi0@{LVKOg%Uq87 zYjzA=CsPLwD9_5TX16TqkZH`Z!I`Ju=9xMut{Hh&9o=YtGF+l$72N9k?%hCV8o#uL z_2QG=E)LPb%$iT}27AH6;og4H9jb^tBRBiVHs~acX})G&i0T-d->e&7nYk^AFe2q! zBpNVJlPPL2)bXbu)_jf>dThT?dULDvX&_Vbda9?AnT_Un-4pj=eteqkXJK8f-cFC| zx>sp0cd0E&eR8FWT7ks)R2r`6G*m?0o!d*^B-WW1hb_w-CR{GlIm*(ENA^>m2qG1X zJsTMxX_e3MTOT$h(O=1?(kE;RkfzyPntAa4Loyb zkSc#YcC=-^h2UeXA>~O7#S^|>Fm5M5Tx4q-*N}nU0 zDf11USzA7yT5Q}p5>W$ZZ16}e;M8uxA1^en%U8lgG-JHd9@lNWSLsmb8|X^X4W2y+ zYVRxs1wF+|<5xX&H8#e3mK;G;=`pF`iA9^^$to==h?+}!xGTc-V~+ts%9KQ2CO`+&$5N)r(LhP-JJ*6{9ySER4`Mo22Hx~p{Cx6Vj&2=xnKJORotRwq zENj^&Y$z7IQFJqaru+N!RSTq%8_vTLNIgmR1doRgbcfr)<0$;Iz>eKNZqd0U=5|dz z(=Y0I|N1B?wJ);%M!K{9AxZfkNa%m+yyDla{rM1s0qv=ndx6Lj#7}SpCWdQ1#My`N z$}>ns-IL3F<{_6W;P5IdtFENonF$_4zKUaOpPCa{6ArcT*&l+#*;uY~Lkh0{21Ejgi~r5f zApLJFhRq+D+|MOR<{-1xv&guW-r+Vs`nBM_E@jC=l;Gg}J%%6YncaE4I zz&PCI&lHVVe(L~wMBzuCpcD$2qfaZc6yGNNNyCqUij9G3hxXt}>L_<|41UVGXA(Sg+8n9cSBfi0kZn-XkN&KF2t zW7aEzR<})UpD_YNS(BSKKomAEVve^CM6IA^%oa#fFEusf=9WpdBC8@!YTiA2@jL0F z*cS&_=A^97`T0Dfy^({Fwc{U6Uy-5~pzi#^YfvJKQ`s_` z%@!u*Ny?ge`Q{^M7n?C&N}cU2r(GnX&VO{D5le|fM4BOlA-`n4*j+qwc&IbsG|x8F}&dri*v>?fXhca$b3J46`;Y4twHke6#E z-6wMbPxB3igh6g^D)%?Js1?P@kfgl?J;;10Q-L^#Q8{)%U`u_5O53$^Q>^Atkv+dO zJWQLw28X{aC~UjpbNs&3M4`6g`1Y4X-}Z`hKVRz8*N1Y0nG|Kt*~!C9^P7DAd7N0< zsx}uzOmj#-VXcgF1Q{hsSnv>tE8fWW>c_qgGW7(s6Xce(p|u#n1JRS6{uqBMN?`gS z?L}6*&}moGkF93)X85Voi0}>HZkNVP3oKH$<=JTLZz}oGypi$Nn8IQm1iM{Iea5UQ zC;R&AG4bwn-(xt(!n7ji=;m&Tmbp1Iw6#kbG8!B?)(|g(R-y;C$0YSl7e!D>QCyJ^RFMhl%AWu(SLsO zNpXK<5(26hw1nmm=nBaBY?zXMNZqUxgmeP>IxUlw__vU9^DF7mMR=g{?fCXd^q0pg zWZ`H`zdB5G4`lY0d42w?p+hbIj9IY)x$7n9g+vCm#32q>K$jcDu~*t;w=CdkEu<9d ze8+{mFCa{lJWm1_z`#EBd>o@{n22&upP4)H<9@tmKqueXoTmhZ>HyD+T0zV?@9Hf~ z`TWdhK~078$V9tnb9lscTo-mEI~OW({#nfGpm4XM;b`pI5;J z2ogdO)lR3e3OlpOk`5VqUK>=?3A>A%$P2xdljQXU3Wj#fkl*I#amE7ICKqvpk?Vwi zLQTQpn7!K#O3>N_N2eeDiYeMuvL5n~=tncF@qA+sh<8K%>hsWV>)K*+$Yj+k^7^~O zGeHN#zjeRBtHs?6fRh;poXme6cm8@Zzk#p+Jea7sp5I==LoU37Vp_nIhd`?StFXAH zb4;*V(>vP!8Eh=kW~hJ+oM=cW%1~#{9G|VX=gC|^$lEj^$&modSe9ZFdfo+1DW!^L{ zj#1s@WOsjE`0y)dJ*xsmN`$=W@loVz^L`sQGvP{=t#Mm^=h&}y^imFpXCJ(Z!~li^ zNOZeTiF`87aqoF%G>RVsw3&!2IF`iw152wsMRyuiM2)BLTD&;Oae6p%5tdDX9-jbd zc9-Cb220NVT+O%Wm1hx4_Qr96^;}>#Y&6s9U{!Ke0u;2A94woJ!Ml7|O7zGmK?7bX zkqC-)H1_9yMmM>jY-kRL0t(+GvSk>^pHKn|E6JEie3o9oFc<#$A^L3Y8p1&*V;#rY8Ij3 z^j%H!iZ`s6h9A_#A^6xKNSfy87)=MK$duTZyu~OvNco!s-b-H?8KPa`SQMz#>IhE} ze@O(}W2$nM$X*5!A2xL)Be0~}W|)m;PK5Zb2epk{rkSbdMQy_{6YzvO(O!E{48e`g zdS!&;AjEtH3jj`1k1`M~ArPG7nD=S1_P%J(A)vpygkV+c8Q{R;5=Kb(C7cb@CE zc4Mabw$d8mqD0*ftxx@%MJEwf9-=IOD9nzdvw~XFT(op7WaL{b}sD z(-|eIxjJZLh9;QI@F3fs$og;Ac*-Y+zQ!i>E^(iU#1Bd2l4PRbEz~tZ5somO#c<`7!RzzKr=1Y9$3@s!1&PrP-HH-d{Vj0|c_<;GF_!#Fi^x#Qy!A9N$;xhMf(9M7& zm7JxEG;hm;vO?{#oxTYYL58x=S*3glc<$RGmTF#j-NV9{2_dtpOdaj@aodi}@hTga`qPc# zKwcPiQDH_qE#nXU3Tl!o2vQL3(9;qAY@s39+m2aw8~%6%zSS+IX2PG~Kq>abTuJ=} zX(&ERr}dZWo~>_}lKO?U^-dpCH$B={t#5>6CB7yAF3=irClAmuf5Xl21GfAUC%ZqR zZT4z{lK1LN-Rc}u=reP*@gX=%^6@PscWU{CT@ZBQeKy4EeTDBj%;Oi+f|Uw~ZNGp| zSZqrEKJs(#!g0lsmgqO&`(rC5gm4rmp9t6oW959^yS zM$Ni`D!E*wI26}XKU6gWTJ?wCz%f_23@)_S#Tc$fhZ>rhm1+eKYlQU?kY`aCOY1gB zst!Y4R9lP=8hv<$!M*5UtfmD>NOiC5&yxdq?_(dmzgn#zMd>nOHK|d5M?QxURW7-E zeh)Td@lh2P{uDBa=v`s3|5hl1b+1ximo&MCbmO<( zw~zd5dLo;KB+k+;xoVFo-p- zc9=w7czu@-oWQ%@2;hIkbRssAfXql_scgnNUQ}yto%8gwBA8XnkrOIe%64;jyHl`g ze9$VfOj@eq-D9Q8ay@qP)YJHU#^d$QI8K;a{{8B0wnzBz{R5%*Zy9Ix7ElEZpl0R_ z`(OW11pr}%IUtMqd-Ra0B5%9Rj_7@$8lhGyL1{6|YjdZf-oT@MUMVMkcjUyGY6QuF z%w_qL{C>mrgdI_B`4p{zfSqY0q7&06K8#Ej6Nc~0vRSyh2%1&ov`Ua}kJ zu3}$g_IS^jB+>5;(5V4K$J`MV>#aa)jTP6eB9%wGzi zzA}1gxlH&1J2t+*yMOQMvT!1xPbiY6`9{Y@Olauly&mA$ly3^fR^lfVYC@n`!bywQ zO^xUjD9$^<0QRYDkiu+7JfZ` zk6uV6(dm{${qb4`BSUi@K4rXbw5VWv#>$(6Yh^tXcSVxQ)>r-wslw}5ELk$FP>DO5 znTn4HV`zEzxlU~~{0epzTi#x$9c(U8F6Ei1q#n$a=u7G*g!nnFH;j+XW6I&)q$Vw4 z_`DK4i#OQiukRl5Xj9*6;II$LQor`;f?Hd}eb4J*6}lLv|K5ym1Qs?*?T?r?VF$U> z39dA(#dVS{so7N+Lq%D2QV+z%-|B$`ml$X9&Nzz(wwtoqKlW33d?260*9j<2-sLm9 z6jnnQ&IwnerjJhq6S`wDn~kl)TvobZxc&$s!5jRWW!f-3C9Sewg=)<-{fFHr59$i= zM2nl)8>Q^m5j1-nPo$fP*k3Mh%#mTGO?9*5Anq)}&iWwuWUFhqmdDcLZ< z-|L(o%XF`&K4L@ht{+qtj(bbJ;7`IdKfPMeW(VoKKaIvd>avK80$D^rOo>mM_7OMG zwx==xPb7^+TgI1#h}n~!hmuSKPiK#%5IngxI_~3j$}J||INeck5mkuzp10`I%OO(y zkQ6txGU)<)vh89D)qsghw24(R6E-`rDK3Z*ig9&~Lfl5~r1^DG^4!Ohfwmd{HV~l# zL)R_-<#US-+K|s;_&rf4`uTvJ9dpdm?y;GNs}J_ww#g%S`Z(3Q*3QgVh7L@A*HaH} zj|`a(9ofP63M)TuK;chvs+s0Kc*-(31`wVo-$n=uSv4y}Q86`N zw|7Sa(j_bsSovE zdZ3%P>VRAOCMAag;xJE3>w`&z{KBy8r3dFT>ynZZN2DFMF;+2GoF1%Y;Hq*6VK%8*j`JY&o1ZK5Dt9k6D~H-v2fy>dOL0 z$OOn?f&r%eAKS#gn)bh2ph&=x>HvD!pmXlPLT$5#B7{kpxdHv)%8=<^nZ$IgG$dp+ zL9)+}XE2nL=IN6*^Hmdf=NlwfI84CSi~|#Wj*O+<{=5yt5PnC~&=qpE(O7#U*TV7^ zhFiFFL&RkfxeCh$5H+S_$ADY+GZt|$B+hEn3CwTaIH$KfC0{o~IEsyfTH^&^ZbFYCebl&(sF}3Nz4!t3vhTm5W ze%RNTcM z4p;sAO29s=+TG!eYP3ymg0)7{J5TN$mqW?Ob;mBCX-QTuA>K(BhGF9<@N)JBW;h#i zVOp8DzV#(_$Fv}rgt(p|?u1U+fCj*fZ=YyI@}-oOK^Ae0Vu{;Icg=Pb|4b$n?a*Ow~gS100ys>MrH zI?h?BRmaAwJdjn(uS`0=vjcQS!9km7G>(lmA3$I-=)PnB`g`&0qnAGdVBQY+z5iw9 z@L#|8Z%u%oXa@u^LFZo3lCAXhfq)s6#@lL;{J&1JW13GFQa~!VJ*_r?Fq76Rmj8I# z+vt=`0MHhfe+yiVS&jRKgI535=INTi>L`(=q~A2s0|&H>yyE)8j|&A$nsyT7xF)bK zJkeQTV8-K9d^mH1ng{t2Yf6l1)E6IvnmLINHoX)r8PA~)jt`D=HZ=RUBXtYv15eRG zz3+lzY#>$UJvI4P{F4+@2_aIQH=DVR0|E|shixNS9^Y}zvLs_VmVLi@X3ed)1Xi^4 zLOG3CT*`<<*`>5Q3`z7X=60?PPsFf!sNOJiZ`94vH?+HV>>vEl>@fH!kC=sk@wr$I zqH`N{c$>y6Q}kY7(U`-G7M^nYo?U}>e+oqFWgy;&F>;!mqxKHvdrl~>GAwjyO<9xb zJk51I%pzdt)|$3qb#8F`xQBf98L!<~N_G zTQ&kvvj}J%3H+CDDLWcF${JW08#;;neB1HQIRnLib6y|zv*PT7#Gz0k<9#xF4?2=t zY#>r$HGl%3yapkd>@+P+jz_a|L>3tz9j8ua838$iEMI|YCUeJEqFbo~Rlcc`e=ip^d*}fQ3NwNtVSo?m3Cw{{?XHJf{n0@N z71Xx0{yBG%zq4r~TRh14D>$>rE(c{rzM27O9!Bm%?XkcN@9HZ5x`2!)H*z&|aBPV) zRSGUx}Li<)EHj(E1^qiI)pM%Axh47sPiXF3~gYVS5*)jv%A0>F$X}Q z+a1GC8@CywK2h^fLq+VC^Y4~aqgizxkelzjw6Q4y;%SozwV@Y-)P!p6k5kRRj9{&K z6BDA0FpyzkGS<#aSSaEt$m)JLKCN%Tjq-Sfd~zgIF=HqClpcys1a1PvPN7A5bVNgZ z#O)T|DJsX!`!dqV$M%gFci;MQ%RJ=dUWhvtPe6fpun7uV;DR_qSB%)k!h06h@bYOmu*-&J-_m^I?ysC8N8a)RZs-3Shr68OOK zp%Q}9-g4g=w3+WE-T}G8OT9{0Dyt!$I~YkOL{MXev>p@jXP!=;fN5TCungxGmtSM} z>_4&hY2=y^*-b7S|A?K-&EOr3nzSwYJlDFjlgaHg+ZboUxHns&|W#4KUEQgd|OjD14=}+ZDpDmAAGV2WE@2G ztDz!biu+lB7q>LLro~TiF>08mx?Iv@fCW}o8Q}cUMTY|BfCFGQ&t%k)im;N{MjyVQ zWTP1}ye!H)-t@BW`H z6zd`wM>+lsq*2aby-#W&l(mHpEX*wF=`QC=(7E4~;PR2GL3tJ*Nt3h;SytinUDx}1 zVb{K1fXwhsHEe5m^Y|Bvv-(>;ILK4&J&AWCvsgm14Q4y7F#3=kKnLJ+zU1L^rl4kd zVK8J5$kN5@AmVBx_&m^|*-l(q@fz>@I||HEr}~@m$%O%y`6<>sn%BTKehmQB_>)c3 z0dm~^|B&Nfb4kA_?$3iJfT5MPYbvzEeir0?5C{25$P##S?T@@SDCN6}qbY=_yjGB+ zukDh2yLq$`yMokcOy4pyk7{%bCH1taj#1|<9U^<98s{ry;Yy|OO%u%bG=;tBK7aQ( z25#F1FBCn?XJFNnn;-h9IT)2v)7BaGjfF&wy||0Lk{2>vz2f^8XOr-P0tUmI zvQK54#e*1}D6Y4C1(rx9{liTj%O`arBH0eNV#x6fgmtak4%+ zMC^UONo`~oBnWk%DD{t(Hm`+P_|L7rQMv9u!ztM#gl4Hja9Z#Xt7*_d0rCCd&)k)r z=1VO`2)0*pMfrMwr%z{U5FCU6qAR+6isb12AhQUODv;bg6#&B)wSgJH>jR#g?$1y<9}AYOYvL865z3~YLG%f9wRYw6J;I@xW~pCf5loNyTm zdN|pyP@WAM!)MIwLaGXz(zK%aprSF#BSQMxkyuy};1>gS_`ZzIaTr5FCG;1;z6^;nJ+=l=%?{tVxKG2uVUmx!MMBS48BKuQtIRDu#?nck7{xIRrR0OEQ8LQL!;@HPmGk%i;@l4C*eG6FO`Y1;~cU{T6^T}f- zrZA4DEG_%`Mx4c;39;9AY^Yk`#)p{(0pY)G=D)AI64pR@sltD+LYYo>HODP(R~xN*hCVpb}av>&EG zNGdBws{b~vfe0P}TC$%@7KO(F)62RZhw6y3a|o;_cOI?${-Kwi5qg^r=!_CEG*{;c zjig1*jna&>oe*`#$!lo)=jqfLXZHRSB!toIvq9}+jjB&FQ=t`4TUg=-teKQ4J!$L+ zXw<35I}fk}3ppGyVDOu5&fuxOjz;RMKxHy&TTqR}T?{BaS$mT|Xx(a0-|M%M^)i0V zTxAg6CVdq8rZe+RAM$DokPwlmv6NzmTtH2cvD2*uAr!cHnmuKFlp%A>b z?@*CP<>3?5@$#CU)lncUdG@3N>%lAn49y^MP0V#Ks z0vCWMhQ6m2)Zc}#ou{D%oML2pzN+OKJ8FDX`fj;=E#I^iMhel<&~wfLp#fr7PhTB0 zh~0zLsJY_#wR1FE7TDBESFP7V-Sa6PI{-{p@yVUH?rBn>n8=5@5oCogrg6=GU8_R* zswmB&uGXyYhuM_JQ+$K5;sz#{-*s|EW=~z0D=9)S3s)=Sp%slEM%=ytI(xFdjh2?R821pdqL|6hpyC4%_dGX1m; zxxpF2Vajx(lz|0Ip1@4jWdAB?w4Q0BP$1%)*8*r9H07*>cXj0i$9?ZX61i&1dyI6L zX5wbTbakznFEw8j`N>a*Eeahkt9rI+!)9BU=X-TmbI4-=V>p+GiBkr8Mh&DU)Mu63 z01raFmIR0#2`1P(ybxJg1LIbXH&Lu*I=b6dygXsF!-0&|P+yB{vh&)N94Ba^YGrGB zl!~H0ME12@A2zN;=D-NG%i$0~c!z$d2ii$C(hm?3$-y}>Fh>JLG159PL0G3xz*ohd zW|86_K^ciC{6LPUHmxQ(&BRVziX+hJqZfDWn>GUuF=>#Kp_=CB%$rogM9~R0Dt`p> z>8X*t8^A26`M{&?K*~OZ4k`dT|1NG3{S%HHj7^Q*{?Eb|`G5Ar|60@%6*v`l1VDNP5DWdIk^b{j z{&?rFEJ)$!$Nf>e_?ZF$CQ||T+(^JgD?wZyOs2=@e_N=~6ToZL~WLm9;L$=`I| z1DD33C5AUNn!2#m#VhjV66nziZhzb)!v_{%TC|U4MiAzQ)HPC^c8ZY8*wYew7XO-1 zkP!HpaeyR|!PIEvg%N~w%WyT6NufkRpcg?$Y`%)tk~ph#w;rg)b?~ygz)`HZe}1;O^i8 zJKcKrIlEEXKymzhBiR+RPOIIj!B?{uXgD6}S+KC&&>P)_bg;(A?P?5rIrfF6hRm^- z;l%Kpwbu;1stMxGSX!!V(au;>RnRF9?OMN6$eVC;(p*m2-B)#fk5;`?IRQ?C;46oU zdIKI6lMvrWU+pCN4#Nh^V4}z0qS|+l!XTvpN%{he(?4E7`kN&G5aHj-*@=J!3_w8Z zy;0TFmn>fW`p%FsF*PP;;X?*?&lvHr>q#{VOR4yo#$t*tyN4?MJY%> zo5q5}2}))3#cZWT$L|yqrno$5Qkn?^~46YPmZ#y`JuC@?*fRFFjLX44G+>4=U9&A!wTsa6mW%)(H$!v)Fw0A zFB4|;Z=M{iPCf@636vML`$>Jbxz*Rwq@AxPU9rw~;e>a>PeY6-WMB-IK)wKufD24y zNDI+16XFQqA08zg6E~lHuO4P9S0YBeDQz#5G~hg@$7-9ntQm@BUB9cQ#$u=RbY^th zLFqEL`l`pOA!}j0|Hb7Sw{u&hB5sv)^wZc!>ImEX*GQiew=t!)y(CBV81>{d5co7~T9I5ItVc(EV8LI$cr#(4wdGq#>zLK1MbmG)@nQFFXuY`- z^6|+>B(PyRFW>_IIKik{AE>e|UR+6ROo6Q(i7k1he{C(Y08(tk5oP;^$vOpK{aOe( zFmtFKOaUA+X?ZB^A0jUW>c-A3$^9aOsR!4}K8Gp5eOn$#xs1?N zDfR#op~%)q4z(`V!it)rO*ZweT{Y-?8bMD{HPyy$)QG1u+wOaX@^YrY5dyYlU z_X=x1GrXAJB&Od%4;1pwK5F5~KU(0H(IJhNSIwiGzstM*k<+cZ*wTOKX$4I|Krlc_ z@$rGKufvzPoMthy0~FSgG^bm^vl3$gx`IyEyfSvk(ZzyXi4s?FiD4P01}{*Y?>j>w z1a{D{P(sj>knnm0<*`Usmb=M%`a zeR0}Cyqbg(HTsWP?v(U#1h~D6hL@dDeZ=e!5{P*H*jdABQs^586LdS|A(~@Btq2Go zM}1@ls=}At-l5MA@7!D(bK}Y0XLzF6Hpy8QvXylcDTF%Xf+b2eq4$9WFi1+32DHMw zQ~N$Poj~pjhsxJvY#9o2Jn*H)vpIflUe z`8@z~UjUH%Z+wTGzJrswzSaLAFY&KN2%vm+)DN%m2%?1o9QWaqSvu!kvzj}h%F=&M|zb`(LD z3TGhi9iT!{MM>rXaM%$ncgyffg7+m_9if_vdMH)vP_1^7fSB$Cf|~)r^Id^f3^hpEeUp2~OyJuet=?XYNV$ zkT43I5g>|a{B};6IdcZ*WACS6tz4Wq`N3pc{DI+iQN%x0M@e*vO&iRj3<*?AiO`c= zA*J+whzIv~ZWC@2&mw%}mr>?%TR}vb7hW>KxQXpkxje~{)173KxQ>fOdTxHHU8)%j z#lbp(01!@0m3Em1FiOog6HX`A8yV7%zB8?)xFd~BLXkTv*(~RZi{JUO6sf z|GrjW#;tZse?m_@;yWQ#KcY|awZZaYQ100%oo*V{x6k@zqhA`e%p^Fy%EFWFBvD<` z46!WJ7^QX{y6AqmqV!JW$QV`DCHjymH*AR{p_&( z4Q2{8KdZEBx2OG&~I7KbrC%6kNg{4->siB3jhoMC!DHXOsOhsEH&t_|&Y zp1YlAC6>j3`P&D|k(5DepBV*I*w5AA(~l8%_^WIWwx=Y@MjFdR(Kda-G~ChqY;kT{O^=Y9 zCl}rq*T=7S==;@?OHD)@UDYD&GPPdu5TX#LI=B zn8$L{`H-+(d~{}zJ%|=hD&X4Bf|=i)#m%)idT};lqq2di+4pJAIK`<5I;Hjat*HiZ zU;mDe3IEBLnKQ84{GZ|RKevy6zVN?B$K~DwecAxrQ3G)IkJ}c1e8}H}V<}rheJgX1 zznXiA3f(e*UQheEs?;`EDD9<5PoZ$yqA-dihZ|w9%W@@6tMigz%*DA4kS0;kkTGMb z*R{z(JB9pi3bI+eLu~BOFfllK{XFR#t)07T)sK&XBH0YhrQSSg@dG~s^wqG|Jxmi7s=_$zi5#$hZ{Xf3jp9FK`T#WUdAZIT7hfl(#>l9Ke8>S+ zLs=9Gxk|Y3dr6ciRXr+lCVSxCR>Oe`r${iV%!hHc#}09Q7%YS7{`ZvV_}x z6r5j(a7nY;&XSLbX{Qfmf~6Lc+E?US{ASW*E^2ebwMPzu+2RS&XA8Lva6d|_WA5j^ z4RYqRM1I5ak5%PJ_bRL;n6gW!%Gw2`iG?d+l`y8e>Vs20BSk7y&F!>5tGn6Ew!F_c z4OM70SG#gPilm;ZYp$;)TCtwhXN&pXssZkGH?S1Ln9tQ42ssFb@f4w178hV1uZSmt z=1l(0t|R4llPdgvEC9v@Gb;Cx&IF(|SchYY8!I_%=l+gfpvFt(ofViCU}T&|pDp{o z;%g%ktSmU*dd z9K@N#6HkOt&-ua?HxtD=YM2h{!r_`@S$&DWh`mz{%6Nt{*MN3`~6R)4*655J@Lbk z$suHoS~8OwPOa8#ND?nL)&#*i1>3B2OxDNS?u&#|^(AtoDRhNc8 z;ldZNu44~M^JWKnU^;S#Vio;Hm-Cd<`ZJT91*|AOWbT1+G}Kp99C6#r%wOU>l35oy zlB8enB1%i#4L!{KfNH4h&x+S9e0Fq)?L8ejGTQFM_s=h6ZfQ~`X!_tncfg`50y#^Obtc)ZMv53+Zw`eR`^s+(cHVbX`C~m@5gHpA|_AYjD zMpnn?O0}C>KPt223QU4M=lL3N_s#}En$7g^q1e&=m7!-nn!f+j1BOhIz{WMg@NJ{+ zI9bnudbI|vzvK_)%*cZsb42j#%qP!?>aV*Iw?SM!7<*2#kue-9${SS2Lo{Hz4cqUX zwmuznyBv7^rp~p5kXeQRaj^ibu)u#VuD?nY|BKXqnqpuE#P)kC(o26~$+lEGb)s}J z6cIJ}tRXoQ*JIjKjh2|ii}Oa`R#DhkNhb4+whnh&XcSCR&}Cw+0%AtSnr^U)hT#sn zrnY9~=ls65Zz)Q-OJo9wn4y-it`9b)_loyYUWxM;j#5I+g?H#gYt6L(^SkwkA*w^*QT(L`5v+lK;6cO0qAsL?T7IN{r>!>zi;f zC}UX;eG9%J)fqXDrJWq3H7Kel1MiT78d+3|VYY`RVFw?j8hYBN@UFlUJh zUH8kWU5@VvJ(6fAz2?^5R*=!_L0e9Y@Ku|KE^cfs*q`Oums{2iUDf3@=a=1vLh;q* z$1^Y>3-BmK1?ZPnZfBcr4@Z}+mVUbjUj*y-<>%FnpEu$8|8oicD!RYdDE{)LKLw}| zT6t-*T?ouVkjGpY=|L!oJ2K*e?)o)O;@Q=e0!2imS=wbI-Q9M7%$zl!!(WMGxF}^z zP8x;Aj$qE}nt$;j5TA}@FF9*4tXT;>>xhaZBP>IXpddF$T%d)K3I+u{oA!QNFbY0N z$#E4SVoEKe;uR{K*i^j%FGDUd-<+NgYeQw6d06ycJVGyjHlVUuL=f%g&FM?VOTj-*46lk6saqi zV3cqkl#;KYVU)Y5)F@15t@Nkh?8r5NUjiCNr&P2B0_Pw;(ux-!pJx}lexKlboYj$0 zRTxvXO>*A{TOs!lc#q&iMouhq9=C4ob^>-g|FTzX7Prd){qcyN+t0RYO8JvBHmUye zx?Ots!?#SPmEj2#{S&p7TMm+}Ao z%KsY6HA_qO$N&s}BVaS|AM0bkJ|zSAyq{M8&qAk?Jb(cA4}ubNy853rd)7h?CTlEu zQT^#G${nq)-WtUfKY~7=a}HuqXu&;_u+#IWvoo$IXj-&SL3$?Ov8>bcQmjk+L_aMumIOzd5Z4Q?L&LsVOPPl!Q$kS z;k>lJXJwWMyEVQ@S;2hd*|)kp)h$WmF&L2C>%{a#tsvvksPvY|)aiec#!D5iN2#8- zQ-$JARFqwR9VyXu{rVMYwTDzifliNqZC5c+GX|a=6s3OMH`@_`LpKM+nm>g*nb#?- zT2awMZER{{3K?F1SUFU{wNW-tnkWM+nEIW&w)@T!gS zRfs(7J|OqnM7Vm&i2ij-)+W!54S_Q~Ah&P8CwTaJm*S{r`0PUeW>R)w*i3TuMd;Y7 z=W4b06h{h(HRZ8*X{7|k5hMd~k;Mp@RX)u{t9;d81Cw+~ z!b}B#mkR<=>i?si{1v0pwl=m-wl?O5GPX89@%krLl_hQ8Gaz;VR)P9RDyGM9^C%(x z`*OjS@%y00JWSb0bv!SL2r3>oFwdE!ry+`Omp49LkA16@E3d()Zxrhb>r1n;sVS(a zIkq915}=SCC-DI;bIp&XrZVJt9)Kf-c8<-NAIMJ@CBut^Br%s=YBjZo5kYEPRlecA z2;$yxyOmf}%`aHwLD0#g0g!RWcO!hkaCR_WTsEWVxXd0US$bpageyIe>)g%gIC^-1 z9N(%NFW{Gje}+yKf!Rg{a{K~2Fwg^D(Wf+pSwJi`EM|QpQa%7$03nTC+lyoif=2EP z{0&t-jMs?Sk1$7s7K$YcoGcp3)>0FYw_0~Mk>`xW^Yb)mYC+>2dj~{BWi&=CW|r#h*F~=kMLepsw8peF4pO0+ zXhU`Tg&UevPk=<$jw>`i48pdB`aCrR+*5bey05iJo8qrd1a7sAJ-KwUKBm!pXxYU~ zG;#okd7-iu08=9bu#wIp+C=^;!avnYc^Hs0%DClIbPg* z%yJMu!H$^Lme@xpu#SGE3N6P1mZq)nRkErySf2e6tCe(7llmcdn`bh~lU8Y@dzn#W zV=~7N&9bm}(--8dUuVC;^`NV`x?wcq*q|>u$S&N=@NA)8orLC0et^oHy%+!ZFi8ps z4kHHpoo()Cz2jCupD%oyPz|q} zYIBDl^ptg|eSUDhJbtp~KFzMQSDhCoKl{MT3GcINQWBspU-Io zOXn?&HPq)ArDvF>KRWOS)c}Y{^1|M{TwQ?8RdWf24IKHhHh4N&_9ZjkV{pk{gY8My zGKEtuW3*baDri#_4maP}27V_LADLTLL-4skQVjIS$^&RFU8GEvlum`1CnasvfHqZJ z^{|WdAjtW!BTi>K)5&-VA}>l z66fF%>!*0OfIrA9JCO=-3J0-F&MY%ZuKEVh08yG2c*G}N3C;)H+R@{Bcede04`h!+ zyc{8Z4${eKopnsX{AMg!SsM)7hBaw1WVsnHa#ezH$IP#5{_*EnF|ggB$=*I>qf7E&nluT0jSX`Bqe9ahH?4#s~-jDZKbl%+j!$ z{#6)r@Jcd~aT4WTV3G;Beb_V+{B#n~ts^Nu#tN<7P&{`;?225gq`ug9ck{33cX|Ap zU^Gk5(WHU!=+Oc3VeZB>(aP59Uf88J-$_BCd9LZ^q*!$Mj|ztel*&TviuKp)BnsC8 z$h}jbR|!GqEW)6d)jp8k>+Myz6XFZOpdTk z^mPQ~;B+trCff~lxV0!}HxSseR`q?={u}9o`NeK`Z>D zmzZX*Nqhi;v_=)YA1N;U!wWIjqITRVP0960#PpNx&hX(~OS;jNJ15P(q-_-$n{HK$ zxTB*)rHN_E`!+AQ2V|0W-Oaue7pZWS#yq$Skyt1Y%h+h+Mk(j?4a_K!iP6MP5DX@$2P_IlIMLn65gKO|EWl$)Plr{xz zy>)QO#~HJYNd|-aQ7hbgPdKU$Igy}4&eI6D^f?96Ix-G6IDgp}Oi{25SPz#ioIPmI z8i4_j1ybP^OiojO2J{m!6Iix0rN7}wcRf7BI~Yb%v#z21sNV#INe~#nsdMlzM z|GsXi{FWCyg3==SwL}9zywAmP)D5Mjs89-fNI-3z1JNVMlLKU>?cN1ZDv9i`Cjg8` zA4Vm6fNH~!8KdDk>!|*Npd`ZU!a7Rd{9uzlVf;rFJ_m)fFDU972V|uYq!4MtpdY?- zD0Hnb_1#3>FD#z;{)ebwX2I%06=?rvDF#HK^V$`=AM*C_`;(sv>qO!E!7FJF5xq)#icWq(8KrXez*4y?+BQetzcQdod_gJ3PA?2 zDJ3gP+|(z%qvS{r_~J%-TDNY-r{a;H)H95f+P~ZTbaXrBHi<2=Pr5Rmg2c9SWc&3z zXtKSv#mk2;^HWpWx{OP~9k*w^EF8^d-nd4AhKKBObWCEt^}ebDD8^;+RjzzxH@!ka z{x>5JB_WHuMhO1r0E&i6eMQOGwwv6u>li;P++OZFr0*hZ=r%{w-9t)tjMPFuj4tg%=&4F-zbbd*Wg4rER54f(wB%;xx>=ASprzx3Yb!({2+NkvmI7 z=Wg!>4gnUXu)!wy>gk-Y(dn1pi#x!kTV7P4Ti6rtykSS#Z(mHOe`+KzXY)jZN09jq zb>OCvsABYcig#;ekR`{OHS%dXmnk}cEIl(A49ls0gO&a(f0-Wr_zcSgX4rfW(xLjdp{0=-$4_);!g+q9y;rir~rdN@|6ZN4FD6scm{y z!H-T->LWf@!xiQ458HYnS0NRorZE1rTg{YDIxZ6XA~efp%%IOLqBQO*FCUx(y41Gf zw;=0BT-$%YGKS_Ok^OTEixf~w_{Wm`uV&*w+-a_8QkfcfGjex3#k$Tss_G#oJ41=#a}O)SCK@qVd=| z+h16Zh5Sl2Bm(Da@mP{ov&aBVZwR_iy{WrpdRi2xP46{oJTvD=D1*O!iPs{p>5nVw znbC`gV&{AzLo=tS-Dl3QQ_ML|?3Ol)ym@SCCrDh(9EmR zQ*B9-q+iXk+MI(7CPs0o(wl9zer;|kdIk3*m&0P!nl}?T_=xgp8DtY2)ha-WE;Rqs zDR?kicY58!l-w|?y1y(*m8hkasI4&HwYKY9a0?U9^2DaM52%8UM>j*O&g8+cPck)H zarCeo7JOTdW_0HZ$v5hU4}sS=9BsY`bBClIsX^ix=N{Ib8a_`py425T(gUtLM!czB za61pD)Lw0!zMTr@D7Yn!FM~}U0@(uD>nGu?)bXp!eyVdYjNpFw2c!p>g7+_tp4q44 zPrn^>HI_ozIR)UM7J!F;tmXcSho9ZSKQZw~vXlv!f4~A%1<$K6O40d49c{}j%v%!6 z!a@|-cTwEOx>|lvHL{rn{y4|&t({DWBTr5QoS$AF9mgK*52HgW*JYH?Rm;_NtF*U% z`HrYpq%xuhc~ZLno%LIR%lyY5W7!;vtJIim1EL=aSx&y7Hi*8r_x40mC6}r;-??D4 z^N+Q2@*uLZN<+10cLG20Q`r!w65X3tJYIYV3*>ZH+V}EzN2R%z zAsHpecNsEyw6PMGhbZXm!L>)eE7Fw(>LlM&)iGOHt(WIC3pK#qq#4EAMwfOv7cnYG zMQrxPS=zq#5?^MMx&~J^FfZ^l)Da9R5J(FpPoF#|8Zk>}Xf>_`+NId7x13y>(T>5v zA@bt5oU{aXd13pudTk~?k2@}WBm;-bRNZ2h(qdEh)|#U}pD(^Qh+Q;t;d|kwd{pn) zNL$}Ga$dU8*Ww=cMpeC#b>hx|{n%fhVnuPk`grro2>U)PcydBZJC1fY4*D7V*E2azdeGSfhzQj%saajTMjDu5q7 zsDAgO?b{)%QfdhLQzlWRso4UrZP-Q|$J`0BqK?U(#L*knlju1iYDw!=P?px^yXuHq05TDXd-T;57d2aEMSHMSLjralcxI>iwLr)cj4g;mx&ePIMhKHlMDa%mQ$gOYuxm6{0a8L8hYUwa1mqL>3Z5#eQP}`%K47j?+}r5i)D{J9%rsS5UGevgHq(Y$7GMyuN)_Ba-5}p?bk7^^o?u?2{i~1CvyL6!BZPMb3Ni0;M zl3CEdfRD*)hA8&iCSa+4GDKkdM?qlWejc%}d|{OKBQkex-as3(6GFM8OIqAsjz(@H zoVj!2&J65Akfw+!ImLEa`KwUjzBiE<1@?Ny-GD?jgj0}pq38C74E8gRrDt`~h(@B% z&DV`1?brJmU&3?&&$=f6JC9Ummw9Mx=|}l{)@Q`}WUhkCwuT`!CpOq~vYiW1i+O$1 z*=D$WyBoopX(637RFPfacD{F;{wJjkV;_G--ih}|e62@MK5}a!>4@qfSBb0oPS6SJ} z3H+wv!g^hM8~JvptJOIz41uky2o$x+IychiFf7cYE zub<*N$W4bo@U$zOs1y>ebJKC}djvHmaikTj#eaiuox`9?g)Dw+ZWI>BhSlS4!N}}R z1cg_u2`ZhY|H{f{8sLZOpm>Jr;O_3O0RjYfhu{$0{T(uM@0!Vz`{n%uXPwo1|GIm3Rae!M!a}wv z!$@NevDYBn7p=QWa9oPq) zLFq27LJJ+mQDQzf#g)AYy4o!miWS=eR>xmFU+XylzRY;WhOAA-YGr86XSRtSC})z7 zFrDUi6FKl{JP8LFTMNHSZL%2SL)_1uHJW_6QGDr~7C+IQ+9VR!Rx#VISFI|QmkiW} z1dgdaOORGMlV3NTLkPDBH6NXsoJIP`fvpIZ^vaUJI31SD9~wGb&Fa~4v-D0czHXP~ z6L~jJ-yjjSCsDgMWD6?ccWrsBLz zC&K-16(~IfWD37NclBi^{7|RBsk))MjgD=r>}bT63YtoCFQ-PX=4j;nG%o^=d3;Qa z?RKk;Zf|SyJ(6Ypaw#Xoy@3yu(U&5hIIhky=ap~vN{fD7Q&a$Uq9B3b_7{_3qd*Xd zXwhyvFn%njM8|1opZ2z(J~h^fRiOmv7D#BjtWd38mVl4>ljxccydUHB5IUP4X*+mV zF>KF&via{jJxnvLgMy#1O~ho0vypT?7SUZoo~o+5N9n~gk4;E*4e&n0EI4%Oi%EmP*y2RGHXH+dgv6!l3g z&APXL1zZd?c7Dzuq)I%pvR-KqIl)V%c_nz~a~xbrcps~tSveG=?|gS;ekX!?{+%l% zP{IdBSyu!p_;fsemoS~w6EC?C!xPF`@lb;T^Mc919)~DJ#|=IN$5m@qHk8JS-ycPe zkA@$H0JzpI;veG%f6r3>&W!(cIs5N0#mcvb78mQDnOYVYLL%Hmed~h@A8eoe1hPp@ zj(Al5Pt2g##}o3y{^&IK17GIEl(s$h@s3jcb0RJK2~(tgtQh3}p4;l`h)5+8mjYdI@cx)4!S?`FBy@b;FF| zrj4lW;QrX0_A|WI40nI7J&XJT<`(r`H*Sf{kgRoz5-I=tc1I&^r5+v5%qyr{8KW&| z?c(fdlqh|guAJPaDo}tjw?HYJ@fg~TGqa;$g%nYq`d%J8+FX*C^Tp8+oshl+FzwdH zT|5_9vxZ|`aId}KhTNS#4fZ>OA>eq`fT_cjUcMXjJCqTap^!5hqe<@YbvPgd$%CIQOeFZ$?>dtGJyB?l;CGiySU!|m`2d%;0qRtOwkR%MlvxHdj!8UJ|5kIb^qL>JC{Kuw$Vz%N_^I z#9|aAWk`x8H1I;)M9RoS!{~AlCcQ$_LJ6!!Y+3{oVdKdjydbpi_tZ=Zor zv{Mc8FzdAf~CgOM}^M^@;z*y3$_)^ZNuu$@PN4bF<0K(iFI^dga>mrC%&AJADjAt zr6TGx)YfLoXhmlrfiL=I&90ztsp-rVP)XhjeDij3_#iswWHYA}b2WrDc7a}o9qa?rUTgW|YnD2>K3V+=Z1yUT2*XlZ<@Gw%DVHOewl198eFOuYiubu3 zNc#m68c*#33T~iX0YGsN6B@aKRpsD8YfBB1L6;@iNH6Z5e7VLopCQWS$$$~BrU)Q4`ObhMc5)$ga*nE8bO)=k<@k{m_ zjd}?1)cr#W#M`Vy_CK(41%Q6D1$gJ~QHcV~oh?sb1WS@|Z}?|vHmk|DTjRfKnOR$h zPy+0oxq#x7eTVUy7q@OrpVqj^W>u3Q=aL0giW~P~=&V*Wx{hJ|v5g>w5aptn)g*GQ z%)A4;E;OKtN>JmziDEU7I9RDD5s9p5XM8mQ=Tcwe!R;Q0#eM?K1kK~Sp;X%ngr zL+ZL>{dlqKc$Onf(Zb-7}y)whb8IN#xao&&r5%i)x9<3N>hQ;_@ZmC^p_1a(-Lq``1H* z&#$c`WARrkO7YJM)gmuuUwC*|%rMS!TGOj`-83=*#;VWM+VN}nIgzlN+zz9uVuGdj za-I525LpI3;xE4~tcoL*wcG#>y9E0GKPo{tO1-}Ml6)HAzM1U7lrXB+@6bWRz zV5u|Zro61LvvSafZ*LE#^D$F6T~8}d5RQb`wVGQJ9B5n~6+we}uJLwmrpxB-AAWR* zkvjCB^V|U*S-Kl}H3-K*(}{}M8Ad*8+EEZ70PXmX&3jT~sPixb4Xl}-7R+31xs>vr z(u1cU=S62dcIC=T%9d_JX0K0@bkHq{@CH)YcL)?n| zi!Nu|7nGL)cDhJe6aE`-*f>zr>B|EKZOe_=A+m3gK`W0_@5#cFKdNZ-2T~w^me`|| zj{d~+;QWqTre_ZlFYAe+yC3-&S~8*sgm*H)3H4n*3{tZrc>QEZ&fXR#P?oy_CAaTh z7(GQV0ErHlpBL4OpS0iFx`a1#B6StD$_`Hy7V~QfX*u@@h-O&ug3~Ul=!48fiO?}- z6~DQKsFrIeRJ33J2<<}MQd*tdvMku^y~BO>J&z;_`l>}jz`g*U-xNtN3vAC=N&J0B znmTl7!d zxKVktoCC6kEAhnJ6WdM)VR$-hpQ3ZJnUkhJV;l`NE7Q_{GayJVZX$yKz7)1!r7pqH zX%Yn0%q54a*mNc8&aI+$QNYoX&r-ER5N-(4`PB3 zVAHTZYTK1DTG(Xe-$7v9m+ctG+B?U5|@nZxWE}{kk8*+UJr-j`L-|F>f-~UPpM{#aDu7 z_SMdJ;CdMak+!B!w_ZrrXH=KHS<7NPtK0Z>n37X=|8`7kX^rotT!htJEUSU;%-ll* z++;Nrpf|pOppe^E+c>0m3)FaImPL=ejAMnatmrq_1MH%%*5J>)B9@sSMiw{B?A+xYiXi>ZQ%pI$Mu0D9sDZ)nW-oQ5F&AY#TPhMqj?Z zF4OGG={L8{1^h0cqb}BZ$q&dV^ZO-&#T`Ggk1*tS%ELY-0uBCq>bvs1}c)Hn8G#FmgWk8;>T{7kN1{ z*r|Tbr&&&=CFA|P$NlM1e<`m-c}`arKu{XG1d?xqezaS)?ua^ zxA{b&-kMfc23o0K>6Dm52JtB>6CadLodxvUSwSIgJJe(}GlcF0rM3#_Fi>x>CV3>7 zt~OFDq(Uji6mVDn$9++XuHmZX2irvq`hE)9CPH`Q8s%7$3?y??pKnI_sOT~}IAWiV zj+mJ^1WcWChQ0NPL|V^y=9*ya5@`n!yH0N?>^OVj$QYRr~otOnc{j{?)wt&bR1LGmZ+fjUgyG1yR&jBw__d^Tm`J9~Y z)UXn!O&jDfse*i!4sA{OdM``|)F%}l1@^O6unHn8i}) z16wzt;MN_YGL3n7FX2I<^XL>O zJVBC0u7yV2OyNVttsES)GY&lMg_2U>@}p872gh;Pj3+ah(E{$ERW#D13(>t|o~9dH zDI<+VDUxr!m2U3(vp7#;t&<>%!-CyAGK<&;Uw($mZLwdW5Js0XMnzn`wh8Uv;-r_e z%=O52Gp%7d3@1G;ZNqEFR|H)vjMm$FbyX>efifLqXZqJf-R4~qer;>HJ7$M(Dqe&+ zLpeQSIlXd8CJ6FP#@oL*Of&x2E)i$Jw;E!%>-BK;RGq#)E;_^vf4zA$G#W?S#XHu? zLuYDqNAPfW5Z2L|&U5Tx!!xpw9sJ#)#EI5vSLIEs*+lFG3!pM z_Foui3u;%O0hc6khD0)=Y&zg$9dO2yqt>QDKbYz_nl7prwedK1tM!b6Gn0$of`>sN>+{N9yJ zd}7$QSNrCmV)SI=P)+9DyDL*5o0%9az^(__{A7eA)zI#D>t!%Pdn~pB;u|8Hqf8Dl z$dbBWj1WsAHuFiAv@5!EX@joLr89_8KNPU6Fe*BwcB$CWk!P#t+^CjNLN_2WS{*A@ zNVl;kUt#53pjG zayuNVc#D;RoTKe*-5~P?+SjWqEQ&Du6I)f92 z=HVS>1qH>aB86NDzPvx134Xw_8|xC)va(nb?FUD~ZaZNwb~)j~4;j64>p~<+u7^7d z9_Gt&mh}ghN5~LrHXk$QdEf8367vJzXp*SDraz=?=gE;3s~@gDHv|u%dSvk;=E!Yu zB3VaUZ(`Ot#SLpJ;tx*~npB&QnrozLr1ZY$CamnDncK80q!?F% zd9~W?y7oUhJoLfWjFD0ZEF16jl}H0Bnaf^`oSd@Mwr{ug&=9I1$vk?OCKoU^?=1QB zEPJ;OGW$d?OLGC@3c7X8Bzm5rjw?!#EqIkLl~q+-)Yl_jwdlQboq_*uf3H;gR97x7(YgjWp~6!qQGK~oPQxJwLSD!Zd3g^IDZsx zAkffYUUOp;kLcs!%4V3_czCZlT|6YapM+MGM`iG{H zf7~dwJXzzJbpG2yn zSc}!sl(sPYxr>U(sU{ik^n*ie77F-_>A=Uk04-GLYstT;!4Z{VmkISn`A$d}6qE+j zgn1*~P#y#4NB9OtdB)n>;Bu3d-`G;z()hZDD@Br%Qm9@>7hWYEd+b^gj6EN?UUQ@7 z`&GDkIud1RQCXzb3T_L`RIbTg994Al2E6e(R#ZUc?t3r8#YW0%CDp#;Udu#Y?*=@& za{02_(*q5i)M6)6>MQu_p(G%0K<`l;`)Z|WlVn>+p`(LxQSo@@eI+!WD_5s7QDf4R zxMz4=nGQ21ag+}3G+fCYhMM4LnW8?BLF3U31<|TU_IUr{y*(`J(obh7BY{9Tv})$0 za}kQqhNRhhQr0RJLxbGlRIKE!@CFbLBtIel&Ok22AnQv zcw*dqa;zewnUs3!H&a_e*MTMkVMz)1WAQJ%RriPV0n8zrtbs! z^4pyQa9aPniA(gq2(B)+7S8|QD;)n*sphYr_qO#P~nZu@)^M(fVbXirdM<5pM5 zFw;10u3Rw8x_>O)St_TV@tK=uU zB$Q^g!`GeU{o7z6-XnsJ0B{&Ge|Q)+Ouw3ps8~M0VIcOq`9POZTY#N(izX|RfC%MC zDj_Pluq5mMSm<%(SD8Hp^z;7jRIEGOZoN+3SiT`cZ_l9#cIHw~?!Z$%)mL(}3L7b( z{pbMVF_czmaPjNvfq;Z7MAVOjLjE{-Rd&Z_>HVa2 zcS*Sv(K;XMB;1SbU)@pn$_@KuALi_kwJHFf^6yf1G4Vz8{z!rCg$2r$<>eb2`3=u2C04=E zi?Be~w7|;j)f~OotqF%c68pz;N7Ekjo*U(WTlu?k8G$>Pv-c?#1|(kQb&s5gRe^Qe zqf8v4;t7eY@LjcTqQpvI29g$o=@a4KnQuwRA;z~NT9pNf@?5}@gE*SAVW#;^U}(Uq z=prbXz?x+*$?iQYi-)G{w7+q#gTJ`HX)Q73w1XfIm`cg=m5&d^mFV}Y*?7zsxwTue zdbzFmGl>qhFef;Fm_#6stHRs&PP$QW{EmOzl_HE*xP$Y+lOVG;splA!X+ z%!RFFp>~rM3#OKigS=roU?5pxe&$X1W>n}?gng8MciY7l2dYGX!%+Ow!?0oe`!If~ z#sb{sq06kNptZwDR*C(o)lo~C(F|2&MwwIYkgOq;Ri52Qy$Siz0PgY`=R8e78bU!U z_mbb#5?CGzAOf<+=0k$bE5ZfZo3h0sDW=)+?{U0*C-kX+<^YdQ4yu!MYq+IQy1cqp zZ6h)&HMmR+bW91cDxYCeS*jLJI@%sJ%$QWZA-Sq(P3dJ3;;I;_ANcU#kqCDQ;CL+x znp8sTo&u}3u_rO3a%`~bt-W-O9Ju4>K~0IKTU)g-pH@TT=Gh} zkqk2vP#u>s;hvhd+E0dJ^y_2?<{(D3%@Oo!d-gZd;kPo1rYH6Idb?%0a0=>baFPZ zHTr99FG`-r4j^l_`b;Hzh>Xa>=i6UAI^o9(Jv0IJ{)8mo;pdD)IO4ER6$nsiV|eRo z#`@)Bu|m?D$evRRkw)AowQ4_;U8O;1y3_xU|Cbu-o{3RSjTF%PWZ&crGtQQcYpZZP`y{Eh@64Gj&5IV~XO41bVulr3!j z4tMOE1x*&}<3zu9v5UQc$re&-1(kRrMdkGPl8HH(~Z?fCEafymwT=6FI2u@w?Wr;at_#&yKp!xUIZArcO6OX-eVYun~P6Z zqF6E>DhGY1%D}uvuo?6MTk7IJrF}p4_{jTg&vU=+FKpySjP35PXG|@T)jyp&F7Dh9 zDa+St{DWn8*}3oZAPT!GZZ;JrGu_*D14>cH+-V}&JB2#O!ZhF3?S&4TqAPNgpAaqc zbLQAK%)hh8AriF}IUulVfWR{SL13+HZ=Fo=={?$HvoqRTCj-jyfw{O< zHgtO1L>D8Klt4mYy8czRRSwkr2jbAD=cRKanA~9K5(hLCDpZ!%f&g&7sInMfs|MK2 zj;8G3z;6TC82dP0@07Bsz%|p}31E+&M498v0Ach+@K#pWC0a!!M}YQyKTZaCA%vd%^*> zW9j|Hu6)rnZJygBwJW^1EANLPS@|IZZdK{5;Sh$?cv>(2KHiB%j~GGtGwFN&86 z4A_@(7|RQu{*t8V4n2Xur*5qcfcgnkR8Z+PwM_G~Pjk~|K8HxPO3s=qW_dz-z-1K~ zbgFg8qb4_v=Ki-%HZiX14h9f-dO+a+r#{+0vItwVI(s>5L$i- z&OoP<5A?Y74iy)rWM>mzGnelgs>(z@vnsC2?Rf7t0B`rDzaJ zWn0j$mO%IU*W2UU`Q)SYI(^s}Fp$_=5V+iJ3f+qSNH8_{(<>V3P(8sK8P*?3uZn#p z_1Y2Y!e;Ya?>xdN6L^b9cs@v3r(%^YXDs&zth_f;O!$h=CH{%C?lAve3YcFIKI&ROwK zzqgMoe^8Srbn8UDK-+i`CCN{sB4ur zBBGi@%f#3PRK!U>6O^Jv?JNw84XH@7(X4Ho8Tkl{j?nFE1Bs_+-I#Mc{8<>1Ulnn_ zBim3(4xw%L7#bug=`3OurwZPi*NTyM$&7i?%;J$ZDKj<>-<~jQ6~k?-d}NA8qW1nq zR)Jft_TD;G=R$9Gh#o(>j&P)j*;7ywFQc$b&=S&MzL+wGfZMNWIEmokCvHgdocna7 z`j10r4Hdd?@N#JP*HW?HqFQ#-XdZvN&3#Cy9#?>n9|QQ1|I=*vAGcZM?TMynVr}4T zVQ2f73r&TxOw9BfmK~GiD1e#WwVL#zW+t7+7@ykq7!Dm-8-yo zg0u&)pM*xF$?%BU3y(EsBnYqv8lvTpnNlP!I6!oWcLXoCMH(v+8;uJZoUPxoE^lTy z(7d=BoQoGl-QzV?r#;0h?9*Ny_FBp1RMB_n@J)T#2^$ggT(eGj$0B%t-UB5R&5jTH z?E!yif#AmM11-~G3~?EuthLvu^qHW<#={K*&Ek+u6Mx|n6Vw~DnM((PPp$#&*x~1t z)slWUxXD`E;SF&Wa9z53ZOu0Fy?QTDcNLdxqkO4rLH z#u_urg9qYNk8U_Rxg~xM`v|nV!+-*-nKWr?_c87e3ALuaOR9RiP0=ivc@b-yth~L( z2+yXqWsauj%uk7dzs3eIQG+(74><*7ij*7u%J)JYZ3;t60|RIx^aM#!wJ8 z7oI1FC6ozn>Foxxh|T_KH6QYQ4}!R}aaCqjQ@#_w!~_v0T{p0|qsw^7vR|5p6DX6IkC3s4?= zOl2LiuND`IO$h}O;!{1$$6fI!C_t&~!nNz|u21aX{m4|nHdM5_64XOU=r|7(t{$lF zWtOLRo)L~;)mJfXc>bDQI4DbcUNxvb=|(gX?37^YT#>|aYIU+YFQ$A(=tO*;PO{X9 zxHfT$ZY1=%c#`-O&1uPNgTed#K^gpIQ@>mPUHn--7)mrzj!I9!!ohjY{L@OV09tDI ztZfuqh-Zom*2;06JcseQhc`7Zfe7D*JFDk+d{RJL zB;v>xS!Xh1b4v&)n`8G^WZ4GdoW{*nDkw3oT|v0IlAM=SihXB~n5JoanGxp!im$mJ z%%_N*stw+i6x6;1q75hI@}epmQauaoY6i)z*Zzi-n8DOw@c@t#J=j0%z5wQirWSwc z97iQd*)6}>)!w5DyHRQKUC1Vb2?g_fB%dQ(G~lYAz$IZo=G$E`pEg+c&ZQoXMlnS} z+vVD-iH}SdM;43J3W>_6cu*Ffki_!>v)sfn!sSISI^NdSku_-f{>s0M*oQ>OoYachZsY z45IemeDfx+Jls&lhC+>pnu$cyFs}yb-(6@JF+(u0Zn6q^3c+S!q9TIG8+FQtXM|#` zIQh^|y@ou5I|Y{8;Mx`$%kxtMccPvX##8q)qBBmIH6WrwFpz(k1N%FzWS;zYLoIPvB=#A2vygg$KhhIO-URw0W)Q zs@$K0UnVg~uMVk$1Fy*74_hTu-{gRpCkGqTlX5gZXi(`xZRq`Mgd-M$nTNeaY`UaB zVI~dpRlJX%NpWN!S!gdW+#xc@S(rCX+K}2LpRcCCuIV`JB?VpHANKy(*`ESR!mNYjLAuwzHP@{{!*^A%vqHz-v>1W-Sllb8S?F-HDr-)Q%jx=B=A51{hE@}J&ATWPmK)pE6=3LxNutIR_=q_%&j$+1w3 zbEcPhbepnq{%fR5!$$=d4lM<2Bt@$$u51hw!P0@FB0}D%Ez!oLD71wk7Fs$Yy8RL(?^#% zuQ^)ph3gu~m#xXr9>_vbB;i$)Zq(|i#2GZuF^?I4S0TLY=!lp)jH1shhxDklH)b82 za|UZ7_MV}Fdnx@zPPNTyk)OU@Sii)s%f%B!Aec_xEPHsoq?1P6Q?~@_EnbnfeIfOT zI~KI7!n{V-CU>^gv%;1dTwz)_q7@TLE$n)r{N@{Jn!)>r=3 z4JiLoP3(B25IVL^ZJ3{JU@UKx!ZAZ*-1+Y7*8p2-xT202XK^vuRyTH;^;a z(7Vpu?`qkyFu8~FThmIxiCYEf3~U04hUB$!9L2qScww4VajC>;65vq3`x_@*g%89z zaslVO!=mG-Y6s4D7a};qH1R;rxVF5%G9yL~P#LnHISy|Mn9$h{*Y=B9glj0Umo!BhNbw&ZFJ?$>n?ZqWN!9TV<(0F+WBmXRc zL0T66%S?kKlC>Aq1D11xf<4#5`^e=p*Kx=yP5ESV9kq&)pVK3a_3eO-t}yuJvRF%< zCH3fa5g+2KG}Rp$W?uQM`~}vaCw3u&ae3!ECgM)X81P^r%&2!!lct~qb*kILddK^M zi_31F>t7(^4IVQ{gm&RY!G4^+2B?cWQQE-C3~W z#6_-MoH%7QI~?gDkt8Od!iPdbY)oIljIF(2d2EXF^jppuP=EUR9*}e1fD7h7=yi=v z%p6Tj{%*%&1>^wofq=DfG&o)K+#T9vlBocQ1Zuz&k}+XXvuU}~MokFd+D98vt{~Jt zD!p#Cc58`9BA!1dL8>dCun!G^_DNms(|dIQc=59Wh=)M<4ZP^=<)ViZWuzYfhaARc zt;;Q$09}!#J!~FOO**w~r~Xbatdssip`~8&^`w>^f{Y=Z#V77oNoq7{l=N$PjL0^A zjA&r=K5T)|74_J0YG$YU?HIK5)l`|0CtHzQt0mjVd7DWNQj2wLiE-i~1k$7myo*N; z{J44$@tbu`w!Wtmuhd>cT9{OAWQveED0C!?Pbj?m_=O?lRP}MNk5SI|~r*KY3dGolIhT z-f)Y7(`PE|c3A)Sx&&X57JK>vyF<@~@fyCjR%X}~X+XZV*@5&F6X>RP&aXc{bXI|8 z3XvAqU~SR)@AcZ!p#JDvcq;3mr0FoSLn}ris3niOzCv5`qnN+~sfdE0i!xQ}D-$%Q z%M`!VnZzC*bzy1cA#7)_cT*s83fc|h>w5%gq6 zT9cIJfi_%p&dnQs06aqm96rv1yL)>Tl@;c?g+P-DA!h^-O%6$)^`UE(<4rvhpTzBN z5G;7Z#1+V0x_4*}ct4bJWl@t#qz^>!jAecYg<>CU?yZyRjV-J@uol-*X>9Rb6}Rh| zbB0;LIkLqewM>?y+%YK;_C46}@5I|%6e#w|A7l&Y$$l=UuCPBrDo^5c5-5`Cxz`Lc zs0$t_=hRVD#igE;n(phfA(R=q{rmk zXfZolw|Sw#&BZ-Lqp4@~Q^Xj7lw3v4m3Z8f{*V5jo$YDH-bp7waidM>9`^}m<8>CU zP+gVx&6skvj8u)2p2QLZt*T#x1ovET8ymJ)h%{+jj^oy7t1qoY<}-xE%5}3E4DhD; zDUGzXaz0c)66*K8bCgPa@M+Ur_c!AAeu|P8a0q`2Y}?rU z7f*3cA>&68odc0R`1N1hdpo3&f*_w_ z=8m!vX`CmJ02&{xNxfO?RJrMV@e7(UJpEj*2^aMmMaR>c$=5_yMo20GLHqXinjb}G zWf^nl1W0(RNolFupv5#OQ20WW*^AfsBU~snv_u0%ihF!+94VXpNC)d|Ll16JqX|Cz zjDKvcZGFwvdtN_^ZhxTMMt!NMp8_yyQuU5aDKicvTpAzEx9jOY&mDPP%W0IWP{2?B zKn0*m+4u2Y<(!s{u3ATS-a|aE+^|q^7IP+oF0zSbQlO}D_pWSVADc$a6+u4Yd~|}p zsLZ-WzfDeFPmec;jTHt_J_Cs%S#)}6{=tN-qwc@e#INyyeJRtp+jOPIrb{}4Cgd%K30})-mYUGa?G16H0$g(eWkG4SWml=oUf{?G>j?n@ z1RNwKkPNPVQyp0oO&?@hz6WGs^W0$XslHSIEvcuUcB~8pzU~CP=}{{MxAqQ|C?aMq z7oXIF)$`ja+1pS=Y;sqtoZCnC*HEOl%9e9%Af8yR)+U8VGh#q6mbeZc=D$IXa2!vc59ZhWiQ?17V_z2>_=_6{qdya4u!UT-W zYCs5Oj{Vt;^gI~SLchs;p~b@qe1T$KuzTA5E`ai7p`fZxPT#n3p)w@7xMG-hGoY#m zeB0{$-se`G4wEWvP94JT&aYim$9`ss-ML`$X-#~c{CH->aEi=wc6myutS~CfaXW86 zt8rnbfLl6EsXoXt4**PA%_v<)t#h&FWAk|H=h*nPRU2Ep7Ls$ki$1GrlW|A|b?1dttp8BhWZo2Q#WHf+1 zP*j>{+IFMAS~31*OYfdHhgYUex_FEn(hphY^q6#&9uxL9UJh)SW3tUEX~clHnfr>a zsfDm7fdERB_7s93V!Ft#R4J)l*emPgj^}wcs+WD`B5)9+iObQWgffx0 z^oU1V+&mSmWI5n50z8Oo!1zOKFkAVR7lGct?{G+5w#-}d<_5(0e{Q$^BgV=mHui5J z2I!Lhzl4~;lE+y*A{2{L1miXvw7R4QM?_(*gEU8;1?|wa^YQf7+XtjJ5VwStBmR_J ziusElHo{WEI^3?Zf!57twkERTOcZO<$tH?A7^PWuLZd!R#X??ErKrid4M)iqnk%D& zwY_Fa_BE&8vl9AIY3!gy&Aa%#_sl+VF)CuCthQ#)6?9+r^a2TT2!4gQxW82ZWDd*t z)5K`*njP2DOm;g`N1HIm>0ZZB-}Md~1~E1f@uV->6R@$w19j${muN1PjQs-=1xgje zdLhmyIlI<#N{xz^jiJR;cy)nN$pVB!M}&B^`r}Au+r8IZh0PcSEb)9p;esNj-(ggA zOq9VltWOUR|7YNz- zCozfM4}KISvX-F_tG*@O3e#~Sdo=yr?|9-fA812d;SMJdD|yvEI<%wzSTl0p5P)j;dRW|Ft^+>&&`kKEfXjq;iN%6@A!(sCeJUHfa4=*r zpR1=3kVEoh=r&L$lr`QKzJ5ZLid&Prt{vuM$f zcZBwy&LwsCfS9V*ORA16pWFpf(DLjP8C#UlX;wFui6lOptB1F`Rr>)rtO8tcxkWN+ zFj@FiE1Gz#u=gmN)(zOd(}*~v)8+pkqJWaU$=^;dQL+DJcu84LK^Edq$WWg7ix3PO zz4d?bh;a)&4#lOVuhG-NzxuzbQ|>Vvc>vdFo)qFJtv5zzBzxHR#aMf)5)Mm};MGi`Ei*$CA`kX>8SOE1ZSSpH2EV0%LNMHJAk)rXD& zBl<-YxT5e_2?c|x#9cekN{MX`G)x=#MHFzUUkep}BMJcj%Fu5_0V?ZdFss%#qCoF^ zBgTZUTX=Co++(G}ZZ?1bFP(GYV8#ln<<(Xn zdBM9ATOhzVV9j-{{Y(40bwEEb00yJfZI`e4poCq1pp(|0+}(jZcEJ|o*qu_0V}slN z0~tW!1;Aij&Vp2*ieU8O9hvdd0Wg@RR;T5DJp&Pj*Crsar3K`wMWb(R-x~wtd{*(Y zCaWd(x(4=*C?J3ktY0!=2|uaw`he^V1=%3KrjQ)+$tvvDs%X%LrL-DhtP!JQ;nrYE z)xNE)*Ep+xP^$KhALDsrdvTkf3!g*>{WLrGx@qL%i9@C^-oX*RYsNVRPD~=xIE~&j zJHk-`g^pOWEir8%wn5H3K|V2xbGd!4f_Swagi_w6wfwve5!?`IDis+97{&@b7Mrpk zf?DBYcq@Goa)-0$7b~>RPkp?f&eyd>Cw(-8T?(-8POmDjw%zJNxgUxFI&$N_Pd zP-c9Cec!*qzEE$lZ=3uZ?2E0aEZ^_?djEL*I8GCeEd^{N37Edm0Ql5!9ac&{Yydv> z@m-n_hf%quCV)@<1O6X;YF(K5*xLFGogHKeo}^Q)R(Mlmo;`r;c}Y^@f?kLdGs)uT zd#3xAL#4}tWp%zIrOivZzE}ZBhv_(ilM!8!KDeX08iAb(`^$#*woP2s4*z=zkG%wu zy@DEZSY&PCAB%?!KI+6M=oz~R@O(+%F87!Bg(COm1hoaZGz@c`>FvlGT zYK}htS)oTGq~mFgBrr8lCb=nU$;C&~Akf z?DVW!`!Z`tpbv!eX-Xpcf%wyVd%o*g^JWxYxHX;jwZ6*njms2=J;|@}W`w+lp)ZQW z)2s78UE{xta8Jc#%5f(w#@IM^wMiwN$+>uD=-S0mOXxM<785-P7D5B=>(wV(RjO|{ z!yrBea`N(F74XU4Jb2_q`4E?0SAO_A-h-p;KetPkkvW%pQBvQTziSXgC~%=KGn4wD zA&~-iTH!FtBWA~At`uU4?7>5AdIIuo0 zcucWY_^w@W@6~{2dnn((Ye3*ifKvldRpZ{Ms_~+ioT z!UzMRG$}YQb2=B#9@H+43t@+vgj&I%f*LI_`pzg4 z@aYE)E6oIfq3tJfO#yJMQLdZc6hV`N+ScC8W`F?Ps6TlJykS^Q|5S%nl(F*%7`9zf zksg3WRq}PiXj&NlfDjO0j@PgkKCG2WE(pea^~4aU2PjW8!k&({f4Nn}wzUZSU@Y7V z7p#?FC4sU6)xv`&K4z5o`8K__)8MNFWxhY#g8)<>H(`QPPH{LG84=Phlw(lYi%j}x zb)bhxc#|J3Wz=+)PcLrIkLqT)o8m}$mK1z8z;;x{5ac|w*`dU@HuDH>`H%hg545TU zc7(loD?fQF@%GHz39Z^b9ybEnoUuas$x9N;OZxv`oV{~&X6v#&+_BYB$F`G>(H+~i zZ95&?wr!)Mj%_C$+qS;9_u1#1yZbxickaIbzT+Khtg)(|da7p4S(WTJP15PmSZW|x zNKddKf^=92H4IxDF}MUxoG=KzIHZzO*oW$O&|zp^hStDkE=s;&wz2sMAROt$y;Jdg z?JBQ#iW;6(K22R>Dz~47Evs2?g9f&JO<~Pkrs*lIG&`fq6>d`=(0YPt1z9g0|A8Z6 zIpKr=*JRuKQ#&JNk#5}Jh3zge?y>HaHpu=P%h8W2@^xFO;#yB+WczO>yj2j`wguMI z_+M3^BBSRs4|oU+%O{UnLq1mxXqcE_nBpGrd!rtU4>7};j|9!J-$QKw*0OBUB#edy zn3@rA&i)RVBw=V}?C>u(?XQA5007n%SV5YlgBbA7y2(qHD&j;&!ui}PL8PWMl@Gw9q;K0aw?7U&F-ww z;q08lMS1Zxo#SupNPfem=itW$H~=3P1aNcx9n9iSvEd)b>5q7p5X1ZH6aT_P3#_J# z9pR(lWc_BTr{#ddDsw|PyjEuQy<|Wt9A?_RasRvW4||aq$_&O#f(cnN zOtGI78Ci5HL;)pB!XSO|hyWEa))TzC4%lG4PyDbql2~oamSo8E#)?DqHH?EweU;58 z*eR89rT1Q7MaT}kK%z;C)X2x{UC&*uvAyK4^2zAxVFKA&gTl{XV|A~Jo@jPdW;GPm z#|{Y|a~9zZC+sy068-vo1D_LH6gV+j{fmoBhN3YQWd~#v>W!6+_XAQA*bAIf8_$B` z@lQXwT_@bX9)7WO|58s@mX268k>ZkZpQlYxP45+oCjOr2Qn8!Y)AUpI2J_+AWp{ll zY()ocJke_>NVu&1Cfp?hDbJ4|e2YM_u4Y6=dePDm82g)=6I<+WJlo;MIj>)&d^&)) z{~c03ubrXpKQ5MkGniRz`9q`t4CdhRZovc@m1Z-m0T@DhzaE{L&z{bJ>CY5PK^?$O zA~yaMZO4R-Yn<`MOuzzS-A6nRe9w7(yRyp=N0ZpB(E+{k%DH6o6vJK6>+*#Oa(+P~ zmDVDxk!0OMtDGed?`aSb@UUwqiUurzKWyh%?=cLpY}Ju$vTwyF|H(kgFN(+^!j}2F z!sN2EaQN4Pxi-Lu{X5daf0oz)JQ~150WfG)Y)r`p^Kmw-r6xfjbe1^?X!#56#Z`F3 zVu6vjI=3Th2)-h-K0hwGo>Raj0$O0{RfdmWcVj(vrzXR$N9evbD)r%Ksm&Jgkpm<> zn@Cx*X7vpM=9<05=?VLl7H~@T9SBQDU;}js}vV*U-@&EC1<7+J}RC-A(eZ z9x_0%v{1lHU-_FMvk8-xgy&4&EKrG!ctnD1PFtS9(;Rp{T@}<6iM4k#9VN!1peYd4 zu~a)Gc8;|^{KlwkeX|yq0oW_~Z>CrOjQD?5!+k`?!|z2>%|(F3An7NwPcc;Z-gp;f zMBw4v>Z3D@xPE5&t%!TyWRO*czFdO$ig|=}v>Z16gg<3$0q8Q8Q+$mp7>KWJc9`u2 z`ur>Cps#oQu+O$wY|XIeP`*BZajrqB5-}xKcdgT}vC(}aZBYn1QFcuaCQt8d@FwAv zdNgZrmPG54QOWn#Jj2`UcOK75411f7eKSF(3dIO{DJZ|XyNOG81h;R|-oq z@M$XQE3rD)8wRR_co$30rEIS@v*(z&#O51cT2OurnwZq)ggRzdDAtWg2u9yo*e1Ai{ZnQPQGtN_SUPs-vsj)%P@Qn{#<&WQ1o;{E(P~p+!&R*uB0g*89b9{1 zUAv(O6->&@SCTVmB^~h9ZfNav_bnyyjMnUh7>;%FW;1Ei(YysR#daZBOtGDM4D_#I z7^`Q4zjbvY7>#U&0k-(nYh(QzWEV+O7ej-8-`^3k;=fA$)n^o<8dEA8_(@4(ovvJO zu~wlAa5uCtZWo+@9>s+7CfC>{79h0_+TpiXC5gY=2xe8`Y9hLKK z4TjrT0^^*|pS1>A17^iWw<3&?()ckWuALXFCiOi;U5^;W@!g-BvtsAX`a;Yfd>ib# zET=}?=s~TAh^`oZ3ynZ$!F*ZSFQ>F^jcR4mt$0>Sv1H;> zqo=yhTL00Z4k{I&sE+zo2G%c;bNDhq%q+3LcbmA-*OnzX z9XT=|BPRf0#vIw}eiinssT*l^gHk@+y)md|jg~0@8us~iw))U1(#dl?_)nOTbCYzN zxsfJ%I;`tr(rI|1_z=v?{_Mi48E^VN37I5`I{CYP*WmUmq2I5|oWDk=3#^Cp?cif< zl8D7jMDwn)S$*U}4&XA+JsI3C_&#e?HSz3S9&Ff^Y9;*bGCSMQB2ex!+QEyf<~NGB zlywPQ7T~+80kYQrx)0)ibbGIDP5oAFcb|<7&>kPmvW zoIw*{em_#M$bx1BiOEh^b-MTVLk?ug`M0n*{_`lJqR4OsycBe8_-VFuS=l8w7Nql`WUY} z9?;Q5hrsL`l(awIx1jYX)*BYFCg=>^Vw8m0aMr*EGeVbdKBtWkv=QQCI?OlWuQA_U zHr&z44(v7UvI`p97nks2xP~5Ym=?Shcm5S|slpx`qyw1U^lzpF#(#pDe}R_&;4m@Z zP8P<0k~UB&Z1^{ai4wpl7%{p#JtsLIVm|=mvneK>uP61GLxx=CIkH90JV?Typ{B`a~Fv@%Epe1Is=6 z@+cLTi<>6QSB0h>&1G@`T5QZtNL~C&J~jDld~)594|4p1w?O9cnYldFC12?@$?Pk- z@y-{2yJdzl)Qo<$1plre-uz$kKki?{AOfA=|DVGk-p5H^`MfC`pIy$+JS)Lf`FwtU z=K~1hNxuK&4ak~L2=X-vht_Ii1qk9xN*ie}02O#n7YcBA4UliG&`-4`1ry+o@bROM z5f#+x3ocs8diXek@9|^hN_L)F={{8S*Z@9dR&Ju&XqqB^6$1MufXvYk;W1qvzf&;X zn7b_{Q$aKEtT-|g2n~C>fxe1fb?4b(!o;&=_!*#XIdrGy`6&2hQQ&*?#91ML$iW$H za($Xc=$=V3(#O@Z(^*<)%aKW{8f#^GCxQZ)2cZm@2jRI;Y#y}s#fNDah3CjI@>h?_ zR2bIw_Nm-T$slMT^yND?@m1~j{~-V4K=Z2S0(^3xznf(J>F&{*;yv^zf#=s$-ED{c zqh~mLL3e!lYTw~6%?ubKYD_=IDbVP@ug*AG7IEZd4NBjuyhCnVW)=nnT1+)8BS})71)<@(WIF{3wqyigD(HNO@1wyHc7Yz-2 zu&?@X`R2nx({M3W3~`&I_>#Ml-xWFaX~_r#g)PzhP;8j35_Iis@;Bcnr^W;M#ohbc z+3r8Ndz!xpu7T&z0D>z9=tz67fq=6vie`WCWoWz`%hC5nr;P82Z>`2yfNZyo6Yu=d zMQh}bWOrA>;w#Dq_M*Zs7Klcj*B z@7)C#cS#sZeQkXWfNJ0^j3e|O|3|WmR`hds1K|%dh>xKGlHDovNCwq7jxnWzWDkD<+z&e`^zx_pVQsr>_+Eqab3Eg{;GF4#;Ft+0fuDa-RWh0i&PrYq$N3c(3Vi7_e?Hs6&Bk8p#_9k; z4Zz(?1GI0&V!`q_&y%Dx4WtjZIn=5*^oBX#L=ubWZ0pBZrf4)?`*lB7=6x2EvT}0R zH>`~{qno(5k=0+IQ89P6LI*A26xt_;>|P_mmOlAyc!6&~PS^hhZdJ0jaQxR?2+99H z+&U$wCXg)$fLj^-^(@RJa><8RIe&v&<7OAbL;O$z>PrITGQ(*)K<5vB&Yk1|H4qci zQR(A&1`*MNap-3^*lyV6E#)CeQZ&Rp@8(BQEiG@^lN3e7I2`lX@8tFx242u!~ ziUL4I-!N-2bArA06ifKteGheOI&H)!DHbI}z{FpX;O8~#lrH1j|3BbXbSGL7`a)q} zpTXy@{@fjQFSTn7C@cK6UG-FIFPKM`r3?2baX95EvoU>K%^GL?tB-)m5YwyN66D3l z7$vDVXSuwQ1B)pB`BgY1?HWVBg%Uu0_ODS}|8-85y{WO4p}~J$nNIWHioXBxoc}m< zYZSxa;MdTtCcvTM|GN+S69|_7*Sr3iYjs(5{~BN62`$bUP5_DUqrl`?7lK7$SeI-E ztZ8hSR5R8WacdQ@mN*wKXElAN?)CkfSv;5#XulEP9x+U9NnfZ_KiU`c?h=U^A;8$V zx-L6R(9+U~+Y29c6p|x}Ut{N#g~G^)(n9Nt#%@T_6K3^>Ito{GBr@46-$H04N_O5@ z(zC|~vr@|Lo=Y8R631GNE2=1-vtWaOUv&a)Aq;z6`P16VlW*1U}^mcD$+ z)Z2BM>r&wWiO7S?@3$+%HJ6&CTsk}0YehP-Be9RpfEctD_eSRg%cH@`)F^kqL^Vr9 zaOURX;Z+v63>QVb)BfbYuL98tjCOfM;+iRp!26J~w_$TxK>DBW+gQIwxZQP ze)+>L6|oa$E5GQQZlOL}8rxR5_$WIZlr$t2F}wWIy2KGX6$P4(?~9<@&gbPPBBodp zuv4bVk7MC?X;nRXVaz@(4dg5e7DEc)>dWSJo??(x=7I%;=6%*tW0ojGjWhjSbU$-U zWafYqrr|SY#eN=kH|1j|G@-ZT=Xe`N;b?-(+l|`Zh*^|isd8xrGJR%l@o~L;)JM^x zIVYqpG~h9<8h#_oOFR7ROJRWJi^G!nRm}#| z4*r3wkf~e+%A~7oCIqbR;8U7U`43y|vI;+$_ylSh_Cb;bMeS`HI+_5~K$m30M|Z~_ zTyZP3VxZkwq31#mU2Z<)aiEOG=^-4SD@!SGSi7oCpyKY>Oa+B)CLtSw*{wPjggjyz zN;I&wh_hFlKpp0M9b2)>@HBGV3amcA4AS>c;`zttOAF6Co+w!wpV_(UY6rb&{(Q~;{r|GFjf zcenT@==;Z^{l|fo8~Y`*?6{|(wp}8HMEJm$kqrT#UE|1?9xb}cQZ6bM3)oA&mSKQ3 z20F8m_&uu=Z-wRx>=)TOe4!WJK+G>TahbXUW;9exHfK=nZc5iaftasxnayQD+5oOJ zGzU-~0rq2Zj&X_(%i21AOkzgSc`PlM`9T4go&;!wl72_>aKuc{D;c~^&b!>E$~Ve% zB55!+@5*{Jb6Y;*ejrE~`Wy8#ujo*fcVKKpxIK>)nb>Vc(UK0AJ zTo8N+T>Yn=j3P)E7!$}lpknU=8|HHPN*LeIY-yH{to!OUU$;T57Ib)>=D}hxznJd# zA-^*^&|`nvX{eS7t|ivb`K)&Kgk1_O2~=oql6Hb`FLR);&hnE?{9fNPVkW+r3w}J; zFN_<~XlnMf@&-b<$_1%H1?tszqxz(UHtzG9aqJx{(}OLy1;@A1bG%yJ*fS}^YMy50 z#7>FYg-2@6Ai$Im7mi;d(C?S+16D@#$}j~fW;Q^)W!e zGAo)v+{X3@U0yS*hdS#$WuMS$jI5LX-99!9#r3+6pcL5WIqx8!RW*ef}YGi zf+=FWrV~{eofkiBS_OgbC4s5WalCoH-yWdBau!kmGmEMV%WD(SzW?g=!BYes zQhvLgA{zrLA6$B}xm6yfHQ`!?KDc6NsO9VN4;qOABb^q(247Yx?pUQpXraA`cSF|% z78Q`V^ZwCMR!1CYCjQ9;Idhr(#?J>zXjUMSckIxW6j13W+6NZm9O-wB0RV+BDbI?; z_7^Mf_|iv0@>QL z`c+N$+amp%0}5PtD~Lk_Hn;HDp)qpzX3l_bwY6+(HJHz5OKy&>MT=~QyHt!h&GrHm zWfXlrGICm+`&$<;tfxjtju-HMy#kn(_dG)ZR<{L=WdE;w@qRz+|F*oah2B4oyJDBs zHVa^hB^CH#A5@!|x{fpyFob&1VoxLQ3AUS>%=DlhO^jM>s6Oc1eMb(pdQF6bH6e5Q z{oWW+k?fKfO-i{ssp`;DsOF}^nEA2NtI*c%w2jr`^Nw&?Y1)*?0)RdGrbtIw60b@+ z{0U28a-R6xVtK_9=(sgcc$y-$ZkS{b9t4l=SL_Zi#*--}juj8=HW{lST|E27m!2er zjM0_P-pA`;N1YwtF{e-gbD!}k>e%HgSn_2X%&{S$NoK-I)kxhVU1ktKcgAqJUzE+>IlxyMD$-CPLg|mDaj)W95?< zQ70a(oM)xI+&D~B&@kf@g9!_f(cCU|eo%JlqsSBTqo`Ul*78$S7v{muNSmd}g%+~A zhZh@IMh=J^j|hPd$}pmnqnkXNXq>^P*1}@qnFjYu5S>#Z{M~_;i$qO4qRf?ab$h$m zVO-S)XgS`d%m$2?VQstuu2RsnPaOtUuDj_cYA)Wlja^hxou0~IrdUUp=OQ&tTY_vO+0050sG^O86j7o;L#_Y(dSU*oJit8GALr<2)pP`v+ z?XaqKqoh1j*7JUAznnDcH`jE}ZjzI{- zcq%hS1CO=>64C#ZG=%G>5tK^2F zOxV!OU4iIugn$JCHyC|`$y`%cirtmNc<511FVN@>harGt4M8cV^CRTfrElvTwwI$e zT_YVh?xn!oin$eB7AO?0Zjric4xO4!uRCQ`T4Fxd?+u%U&40?OUN<0<^)(~UJQz`| zUi=wvtTYN2F&tqPN?G(wg|s=w+tD8b`%qN#jbwhpUV&RRxEeFwaluM`65QISddt)& z+Jye&oKQUG;B&?vJT-vbc3`{dUz4Ra*C0@$0fc~R5pICwD z2gRXXD$EGYS~E&s7}fmElmT|ga0i zu5I{SY-gn+cBnG>k$OjB6_(q9wTq=kD@Ugz3rhqkf7dGHeZbylK(P^bR{wnBGJcbx zXP!~t*r5X5f+nd*Ez&YiavVx&PDWF02=qFtC4h;mqfYPvuUoHOd7>t&YjcsaOX%!j zABxT0uBd3XYw$EP*K^@KA|2YZ>9`v{%uK4iiJ|#;p63z{Fj%qT!PlMm(7uaReG*5* z4qk4Ej^nvDx#&3-UVRa#4+MJ^+g=MdBZSpqV9d$XGOO}<)Gm_Lg{yVDCZp<=Z;m)E z{fz|3q4YS!#oN8F=Wg}sHwOf|L5fEOIN%(h)cE>;%P?fD?M)p_o&MC>$ZJLcwk3N^ zRH>B6jSw6?11Tsh(=EgCEAL{u^gl@pu~-Ny{GMH~b$u)3^&=90@8{#kB#EQo5x+Qmm& zZ{_-OS+rCgu-HgN+Il=mFG`>@F0F&pO&RP+C9|GpNv}1i%+_qHeyd!1f3^Aa12K^u zs9hm2PIp=wtx;tbblO*8qj`}8A^}hv(D-aJn2eG*gk$On1E|M*Go z^omLg#$<8Fp2ih)T-m0``c2L=10%y$fCK}EWx+9~_6vU>u9FZ4hp3bOXe7pGVA5fZ zZiiX75-DnK(Unu?wd=gGvgxI;nG^h7Vpm^{^GfD6&V)t=w-8$8vk*Gqf}8GLPFnn_ z!1eZNniMap^)${trfKo}nnE>6ik>?^jr6oPWJxZR4#$X>p%=QF7pDn^#Mj~+5)RTG z)>~nurY7O`qH9nRN~HjV{fajaP|f;#K+T5dzn=i#J(CJoi6%9wJhQvQ@ExYxsuesa z3>AGuyY9fWAz0|*$mx#$n@f1&RNLkn;ID5CM6tjX?J%VrMhuWE18Vxy?q_)5@RAq5 zjeZ4q*}pIm>i_0)rU3q?sjh{o+aGE7HX^|d=^F>gxK{zW zm&o6Ixj!B#W$hqsW#KCN&-eaQK2i|($9A>AbJx%qwhySx2tP=u$mI$&odSkknH$Is z5eLR2Gn7<&TdO41muriG33j7LU#?Z(AEbl6ccuOiuekAb;Fp7HtiPJJfCeZ{>djpHzI~53v$_x15K?G9qEND znwsL)gd2>&O;>rJDbeJ4ft|pGlBRWU=2&^gGGg?)FEI8o3!IycpOM>yScmb2#Ay3v z_*EFSR5rW-@rSbOmlQ8Z@8sO-&S#Bf+N;lP^{At0*!bL$4!$|Ch}_u?USO$$_lFZN?B=su+GUp9D7_y`ivRP*a_rig#WS0o*R zr$KRpQ;b8)wnv1%xk8nP2&k?WP>4p}hr5~cR)w8e6H~i;?*g3%TNOY`7c=(JOH2t+ zpd!n!#oy43hx4WK2N8FnQAHdC_B)JPvkf$*kPyMnc$_oz6x_V5T9(l};D)%EZ4@nK z^50Qyr)XDVh1kWS(YrD@Z3gpW#|+KCA9O<*Rf#VkLz#>{9zV_v5Gf9?wD`fooXT_# zfBGPkvW|HyMP$l3cA-ur3QVaHXovaYC)}c6T?GoIrbx`E&+q_;2df1Z<>9fw=x1gh zR5_`7gGX@2vT)KK2DBREAL9gUiyfsq@}6xNb-K$QbkJP^BkD@Jd$W8NeA3+@VHFZR zZA=;V^I&+tnd!K@UITqTh17Am_rm`mf-G5!Vfy zkS9s5-KW?bC6Fp*GU7fyEpISiO%~@#18@GVNUStKtP&am>)W@^OwV02U{UYjlpL`N zW>f?pL!F#r(TKcAgV+v4?%Yo%CNj3FWD23kRnen^64mYna~RS^I?pp+TX9xWyv3M< zbnvx~d64EbuuK%J#?O*ii_#o|99NH#`?U*xAWZ^2^V0;*tk0{YBpKo41g4KEz31Nb zJ_l>CxYHL9*W9x{c4dL=AMzC@GU$y|@`l~gtcbN-F2QRKX5f)GAAW{+p5s>b1T{vP zZ3atAfXqFA(TMR0T2%=`WzL)6K{f7IaRrqFlhj$7oK!e@ZjdeMY)q{DP)4;p;J@O+ zYTN|}aY<5xHvE_pFwBx4jLME1uwIhtFscP!nG>@S)B|IjL4ZBa>;N2HbuG(yaw9u^ zzI0%+-G9CR+&8vr!6nx17SZU=$)ol1$mZ_ql`6T>vodh#;l`>yx<|8m+N4##yIswh zcRFPjW{p=_)I`@Qz0W$MZ8daxdH;BFxasP}eJnYsyGjj3O&q(JtdS4-zPwP41N6`b z<>ja+6097z>{h`Br@Lnhc4nCyyx(s%7a0WieO*6(-KKnd7af9-z+0Yoa%|68Oo zFtqy*aVkPl(t3pr01_y}R-?05C*Vcrnv)&#!%O@XHQQU2(l~#ri0+gDPnuNP1B7M0!-$@ZbNm7 z>WFF~_n}RgKF}cN@uGk7fv45R@e1JlGMrJw*lA3>dOJ4*U z$Tc0L;ev=cdIpA!fPz_&e5syYx`!fy1R1~#bqO5T1z)hnWTjVs-6$dQcKmiqA3;Ho zxsN=YB0K#veM5zmeVf4}jSD@JkS4T#3zSm;4tYm7pqqfL*XES`v!VB>$`9==6>?Zu zj8!ahO=RXaFoBn**ry*CfaFv~*fgGfOrK+GhOTdclTxB^6!RlV@llhao}B;6ciFJd zA2%>_*tMTsH3zEi2zKG`<;_J9$QW`y!0JgjvtP6Y3>utYR&1Bl}f$$)FikFXd zn4<*Rzt6T7%bEw2}F*4AWZq9RMj@y+XG|?xVUDojCDH1ZyTJk`Fqsm*O zdbBvJbXUc{->s7ANhVb1gl}>04#L^@5A4BVI?0Ma&qT*6s1^|C5g#{=WJY;G$4OCNI*mEya9HYS8UND zL!Qw7q`dS&?o_zaja5>mi?a~9(gLnWyg7^Ot zT>ceT{!Dx`6jmYu1)=AJa`-HIDE>2$x}pVvB9X1=Qg);CARDrth{e29DEZbprxY-X znqaFZuaTY6-a|UZ`KR?-X5VS^EaSnZV)-%XpH%JK5FP{psMP44$*5vabR;8q+|nqV z1vD0m(tG<7m7b&pwafx0e>U~~`fZ4t9FFvBNH?a8`;wpHVJNV&oxGS9>MBf{k1SXO zOUx9jp+$drS*P)|l7noj9MPx5EgW{dLHbaP5#j+{Y>1X<^`w{Ywka$@y04o%&1q<+ z=}uDc3!74;2`sBQ7@f$`C$4(wO7QQx_m|p@kSUP0QOn=mmFJ7+z*_>sF&N=U@)b^P zPKDKBFjcp>O4Jec6`OGjcU0r7(s3M(NU-Ceu+45TzQ${ER@OVcV%IP&@e<8lQEGJ& z#{@bz-Jh|3g|yx^K`Br}Slf77bMYI&nrv~0dwJBu42s)mXDwFlw13%tz1+r=t=8az z;C`UOoBp#(`$u*8M*%0q$NxY3CGwi~zwnIvs^%Oze}Z8Iks^Nlaaef> z4L#`lth<^;6Ua4d2#D@r*N6mm3 zA5=+yeUerohsi9T@FP-SPeHpb1Ph{bHbb-FhYp+2$Vb2IScI5hD}g9+!h9n1DRR>- z7o9mFRI=~>O1c7~tu(bNT5c-ci0(CW>^kXZB3d2YKlo8Y{0CTafjdr6{?fF$Ww8Mw zWs3T3Y&>{-ykm?npI{$mW`bkSRm&P$UmV@A+saUC7Lg?lz!r~*G}!m5Hm z$*G>mU6Ky*NGuk5krbZH2c?AAWNI3W2zi_C?HO9(2&n2}S6##7;eNe^ZXM&vmksfd zZVnJUsVKL0kdC}pgo^&5;|k5aS=EuYOYk7sD{#xU)+*m|qf27UFHg#A*)7*+dnWZN zH{3V-mvQSsok~5eORIT!k9A3jD|-d4uBgC!-(dVMO|ZxO4wb*L;7M%{dE%`J_USeY zvp=%*u1ZqN$rT0Gsna+KQRib|MgS;BRb(SW$*9?aPAX8`uAU*`(H2g z$Dh2D_xMjQVi$;a)8uNxXs@&6+ZNy}!MWfZ;)sU(@%S_WSqrpad4Qc2Dd^I>V!RkC&IgHE?6 zf?b)ld9Ivcm}d0LWN_wWZd3o>B-&?-18+nA_F>i87%yR3g6{gjFdqrJ(P}g#17Uep zpBZwG3CdCFLf3Y;0zN7$@2X2GiS6maqI85pHU?DxpsAOwl}j>+vfDl3r+SGqq3f>7 z?d_m1dDB^CJC4_}KYO&N=C+?~Q}TzNG|lKbaPW53ShpzQ?1^fhVQ)9)2F>*E=Nr%> z&-1?gHEy~MJWKllF8(*bpy2;1u>Q}k^^Z;jU{-M2FM%~G(Y*{dyUI{a2%$z$Y2wkM zWA$ulX|5qRxZYyHNbD@%i@PzyMz3UfA$mRLggcY#1j7S$b4pn`V`o7T_^!}O&D6(k{a2CTyC%W z%NnE%>$uW)DbTXc>~x{ao#B}Km<#11H)JJm5O)b{mmEUONLhy?C{c~pTP-xel6k2W z>;8;0ntKm|c8zJ-%v|g>8=ykK7tV$B6BMv^aDmujNh7GfoCVyGrcq8y;uCHl2L=1> zrP{p1jfl|@zQph;{ir5TM(Z^6+;z_hImUX-@ue_X^2y%jC5U=(w(wNM$%oL&Adt|j z{-(Ti)l4;DB}59*xsf}R&c%Tg_9>c=NL_bn%*5oyh-4nsV0>NF&BB$s)Pj|YUB~s8 zRyOC?jRP~X+#^ctrUk_%AjqqXdjbOvV@sc}B${PkH5iH7g@A7PnBgi9zTU>rJYi|F95bG*s|x94mS>Y8BAI2@2r{2qr}%4 zhz}o>Q2rMjioZHGKR{#aU}*o(&eBSE+G)6_6hiHHN1i0bgx9IzBcspLxBV(~UPJlGs?KnO9~w8+B`4Br(%z1qkZ_Y-U_l* zoh$*{B8JW{2Mk=_sSDnFS@BXEYB71+PQxEN&)z>+pM9||w~MTbtX%KF32EBOp>UvW zx9hGd7@#BZ?E@B0aDEYRL|%lRmvJSjpnT9J&75D3aZya9ymu=r zZ8u5l{wl4Svih^6-_#A)Uq$gKa7J1=2s!|sw2j(Mp1dYOu?(IVBSc3jYErRSE(^Z^hx_9fZAW6Y9pm##g$;>#rE>LhmdtehRellYsV4>nrdQ51%I zK+Tnbdm~1e?s?~xvxyij$N-B~P)b?Pf_FjGsACmH=FrW@8r-NdkBC(PyWWs~E3#YK zI--IUtA%SI4AZkg=AF*ehWD_k%`fG!GbEi=VzzL~^VQa{m%%qU;{|Pwu}>eAZNN$; z^9lg0*_ox3vqhnb6%`u~4PY4XmF2dRZjh5%jj#3H{)kkTk$jS0aKVT3!bF~${)T48 zfjlx_2k&BVs8^9ev^bE4`h>EpPtMCK%m@zDNfPvdLDia)xyO7`n%55KbXp;s*e=~_ zELt(63T&D`(_b?ufb}-R5f50b`ODex;JvJT^ z6m_3v-=N#;K=E-ZGrUitkoB-Hhc$wRQ`pu(w#c=Z&DSa$TsK`na(OkTQjZY_7tvFv zIFP@ZG+5U9H<5vM0iS8*TtQMcW22bKNQc~w8?&)lyn~WKoelI+x1MyT$d;ib85;w)C8dHr zt3ibd&M*9hOYQW}P^wQNjHr^(H}P0i?6)l8+~|XQ{!!AEouVMg5`y`dC_3Xau%k6c zQA+BWaUCSN`8I`{2LdQt!TViruDz_o*waVZntIchrXC-bC?!G1#LVgfW(t^@I|aCk zMa19u#%+|*oplvwiI7bl zlrntgl@TEq_z5)Wg@}$PL9}i{54A1A=zz5Q)|7Rp3nwC{K>%6^2E1p|HgWADEyp=@TyAY_>5^|+`gXyBP5Lv&?% z$MK~WuYqWuzq~MSP!lFXb1LzpP)EmyO3WP2$uq)@FSCt}?3!|08cvKJOng3Mq3M4-2NV+vV7TlrP*b2QRk*=Ve zGM^myu8jROPvE*j7-4%%O}2pgDq8Gm6`M;^vB{UrhVJ{7-*F*Otq?Z86_x~Y>^&UO zZO>kcTW$(=pGauDGPm18gM5UGb(qq1#9FhgVH5OlL&||HPw?u^$wjb#ua9Q zbr*my7@{@N(J>HlMnl2&ubrna(>=0C!SD~xR#y>Pr8tOgiB7i1A)aL{bo#Y*zBzMez7t=hyY0U&0-81u>vZG3M_ZGtAf6b_%o#p!6~io@lY>_A1Nc<>GqBe zWMnUKQa%`%2T~X)D)NbyOXnj;*f#N*3=eElbLj2i3uBN|%E`mEBKq<5%zIW?hbI{G z)~w)o-?M%B3Y@F0INk+G4TYqAuDGXkY>j5o2^`^0tqY^(C*YTt2$!qW_m0T-Z(icX zy^FyZm-J7+A?#Zv-z~NQc`z8_|6(coUsHyE<_f$Prn>)-^j0XZSYfdudM+r#VrSO? zn?|4r;(hFiK3=p8<&d&0;LQRyORD{3pOi+jP^xpV?jE?KOHw&gdCE*Y>eRBlRf9HD;&5v1F3tQ3>YNiC)Illu}r`FHfYN{0vzZr5~zD zBBqVWG-ITD=;XA{E=jF+(Lr%|AI!SI58LZiye3Mh%;C1}LP6nvnjkJtxeELyv=GLy zO|u{C0tR z5DrU2g&cTT{hT>jJHz?`~=@5|MtfTc)s7~~8Kv}F5>ccBky(Q7Yu*ARyJY+ydP zg&A`yGm7JnK^N^VIbCl+Apz0RB8HLlssSj4ECcF9X%Lp1C_b+J|)G~Z5m6mSmtHaxz@`=&kA_xcAf$jRaBq{ zFv7fCHNW&rAWH$a%`B_5`dQ@tps*jj4D4Y@EO8DqmUdQVZ}LOPZi|mzf~U$rkE6u` z8)$N^OGgY5&6Fo^AIt)n&I}ccal8FGaozIc%qMADrDPp*7q50Rp%lKy46O(m`vh7K zQ`H{5K#}o%HVgCChqv&Q$dh4?l(>YJ52^)sH=ty)2Ta9+0S_1-v-D?D=qx`CWq&cd zO68i#hq(+!I@72LlOQM$-M7(7Nteb6)KFOR;l+$W5NQrBO^l)!`qb%0rwN*A0u`JM z`L@YbZs*cF`s4GpkBtw=BQ@%$R(~(0sAL$MlgP(p%R{Ujffd13e)@Ruv*vr&R{#Qp zv=xTEO``BsWE_*(ICtJSXGFSz!yWIlF{EeDR`-mYZfMP@c#|2ChqiZr zJTenatLbo5;4#fIa2FWa%L3MRjPW*Fu%8#p?959_xZV*KGwqW!HiEk`pR;jgimeUX^A!r8~iF8j+LHAWeeZ3oi8>WuqX zrAa)see1!{XYETC_2hXXKxU?#+GLZG#oNw}iZ-YjQ2WkaQ5D-jpLKmUD8e$I;x8c7 z^g50%7n!bq8i%%irv`D)=|U*BTD!s)p1I^qdKFULQgqnmJ*t3z9?%({nSpYpPn8T> z?V%(^-Pp?1tGvMivf^I7yYg6-&?QLX4$t)~qftHAA;mJ_2+b79Tb!iHz>xfl=mir0W^E10ap7FDgs zRH7umj=(#YKDKN&T)OI}8jhz4uFA#vVb|8|1;CbhtzPi!dtSNDf!OZui) zTgs*-9{)pfy36U#ws%9*FKa+TF;16#LA#S*A>WrknxpTz9_|>9^V5vy3Fpt9lmfnr zPu_qgojIUM_qS^re||lFFKPVO3-XT+UEJhvx_;mzfHrgylo#&yiB-S~U0Y5b8{I`& zIuokpTGl*W1@ijBMT$s(CU0YPZ`#3lN-Dgr7tQyUifEY_=cZ9qh+vAX*oQtHk;I&4 zleL6Qy-4cRGeFf-GB zscop2aIFC?>sGeHvfsRQB4#uqqK6g3>(e6$SZ(&A z-%)z`kLWUjIhNVSU+%|ltoQxt`Z2-}00Pcb)^)EAbN(BvZJ{??9j-dOXx=-Tj=b7Z zCc^5}53i4NBM@Xv$xXEv{m`Wh0qGSR9W{*mVUo8j5`K3tp#9d_ev zaiy1jw*m-&?h-Q6NTos?er~m1mAh=6{KXZJG(40E`F$)Tn0%()J7WdtY?VXP%%v#Ark^ zC5y6nCy(7iserY$4g>sGX(Y<@Y2O~-nij`xH2sf2WC*M?-J*SZ=BZEbWq9tg;Q019 z2AEQQNYx9BqAF0S2K3z=mg(M1euBC0Wa)XcfpeUTOe+5Ej!3cRD&>ssgL9D14+5B> z{(=fHm#K!D6zYTdm}saZfsW%egbmFJjW&*Yno-v+BzfZ&A5!}?LvgcwvO#X(x*RB} z9o%L;>=jszpPONJ970^~U!;YZi%RFavs5@!e$0vo{)qJ}gkg4$*F?rGH0Ab#R-&GZ zvStryD*V=mhh;jBtzmx}=Uq4hMOIGhf7)w31sNJ_PwvmTP5;^AuF0<8oFxoTt0*&e zAdi!x|NF^mXC=M8v=}%^W2`OS-awN$JTSZ<+fzkFV$O`_fLe5Dn=0wA=FhPt-_?Kk z_a#}3`pG!qtfkl=!Bl>IbuLlFU4ymRjR@Zi5qm8d$W_kG^BzhAyEvVBOEg}nzkJ{9 zzjMNO`P7dBQH~&_Sd2Jbz>6NQOz^mzEe>bS6^<2R`me90mg;jJSco3m>ytx-x zDQ_;~-h?>9H2;QW*s4aZ#=n^Y+5ADTEnWR$<5GiiDFj7{p}j54+;DBnSGS zfKnp`JLhRCwd%7oU>^e{tlG9$>nf zJ#n~?oGBSME-ah)UJ3Q})<7rDUH7O4cbJGrfFJE{oN>V1w+Ok|j{X&@f>5^fr0pXs z8V$!fh%1W9L7}zqU?`>#p90{lVHAC}vNP<)u_}(qcX6ri?{674I!g|Tk=GM4mnz~% zTRO`}ttZcdJuz6rbtP)ZQa{wx+SERgfzf}38O7WkQnj0?U~%eKwHXW`)`h+%OqKB_ z_Q#w=%#T(qVS_21134ba0NdpaDJ5vp|EV_SkhTp2v3GLGrx)E+ysA~P_00xL<|vV~ zy!+3=fq+}s^LrZj3lJQCtDN~~^#9EX{I2`-J{-CBMD;Xct zJOt!M^zJVwFVu?C7TP{+ul|DhrJ(=Ne@-zs9|>5jDtwU*m4u$yoA;j6sZ_ClwtF~GIqeoc+?ajR=;SdD_9oO>f`UFBl zY6IL#ln~~~ASGM@GGwmlc^{(%3}|5*UkO9oLc!ND+G0a2`d21{P&Fc^WR~PrHz5b|98Gj_P_eV|2SK&r)HU<1dt{Q zVEz|Qp@004KRzSsq;GF%WGLwNN4~nDVr8={f(RImFpPcog`9XK#Xv&dBC&!eXIRXX zQEq4&t{JYAbY2!G-|cpBw(1G3mRGn}M4~h1wwa!&XVR&4>@|jznC^3oItF&CT16&E z)Hwsql{^02L6^b~1>B`YVYLI{p_i*?kIqPuXp}^SrBl|Rme-Jy*-?f8p)yY6lWV5GhEyjBAL5?G%KT>Q1Q9q14Q(Db_b7BgnUDuz4(Fece0Z5e`QUvRH@%uY0pU))IdeE?eCBr!8nQin~4VwkXb5>R&LrtEQ&qGu0<0@yL78 z2IU)f@)q+ri>yeOxe1~j%?;D>1S9f||M=8aghaYbLn^)w#L6A0qF}4vuH{aM%8+S6 z@=G^M-AZk)v5<2%ePZNGrn|NNJcbtSn4+#4ZJ*L;10ko_sb~sRXh!(?IJZ_vS*mC; zxUiS={`yFOJb#Cl{VA!2INI`*@ev>zFiH663oop)St3^Pmd%-+7AA2esl3NTGZSS1 zs*j5Wf*Z8r;;$<&4pSe!MwxceWvS2T@cFYnUz#08Trad&LHJIk4X|@#umkxNN7r0N zqOtPUX|=Wp`_S;n<9>ah?OnhpP>BN(;HFtS;b{49=e^#db9sInPvoDk921$zSNM7- zs#*Y|bh8Ze9E^u{_vn#-|II%j{+Pb&9l6optCdzGeQgSQ&t~tZwL6Ye4iR3q>{Rzx zJLc86bFb&72XUzb!7@>-B0nr4%IdR_oMi_omY7ChIzy)3yf&%7+($N-O#5dl!>%RCn0z6k)>}`KHX7L zd?2yXv3|w;-Wf7%vz*>8gA!&(G=N3A1+YT_O#ejJOutV z*HuM_3z%m;yz+zSne)lHh7y_c`%H1J=y>R?@z(sf!F@Cszdb@ zsE<8f&}JF)ef%+>c1Uw@;7{O|<>{ro?)Ci3_uC_mxCG^=cN3`M#Z7{S$p_*UaBq-5 zKd#Z8%3b|{%qtcEKz~~^{|kJi0C)&kKXWkqX6YtoWNG*h27==3Z^q$2SKRMC3HUXI zX;ksdp;e*J_sr~Aw})yK*L_7oyu0Cc`i|WNrFHWnd6-VGqa+hJs-P+~VOoh&d{Rj;4l+d0I8mG3{*lC?d~Be=HMb<-$kWL zT^FoQj;7*I`s!y6)krLcB3LRsUd>0o1{HD(OrGI`=$a zmqpzKagXaZ>$8`F9SWK1cu`ZW}Cci z<+UQ`tL84j)}!FDJK-=UpLadFK+6|1nt{s1;(-JSvZA zDX$88xigsamGQ-m%lnC4Q)bvE7wG}^Sznp5K;*Ku-y#&7JG?lBHh!OyvK)=eSFKh# zIoI;?a`SnJf8)oOGlbbMe-4g$iaGLbK<3o}nBsH&?;ki}YX^Y)m&5NE`R~|hR9cq- z=%D~|uZV4uoFOkdR4f5v1v^DZS!HFosg=#4O(&P-0LX(au2ZfZje^e!?ClPR&Qo^2 zv&bmGg(!Ry6dG|+EQbvW?yLAusbNX)*~s-E(ea+*O*ln^yK#y2DDGorJ3F`X+Jkt(;~v+`v|oEhk7OT6vZuZtN; zXk1_SXear0suOEt<6w4T`f+t?x-WZqrGC*0N`hO4CGkNb+sPvT%$+fWg}~vLj!|g( zgrthZv8qJV6E_uD(Nh%hIVx(LTJt4ixey)>NveQ?W18dk`w&)QN z09r^rbkvwQ+;K;yx>F{mt7N)+uFm#PZj5=`c~W&JSz$c_BV+R=2K>n0!L1Cu5^@<} z-35TFMpcILD}7%b^etg%$G9$V1$*<4G4oA4d-5UV#DQG9xot~RFE1-L$$-@g!6yFnycMD<=5ucVn+ zCUiag+@vB$MYZCjf{&nq^X22TU@m->qfK2h9D%yB>*Rqx7zkgv8OVE6jmGe1&xB{) zG`f;qZyQquJKV4MWDDnhhJ%(W9+^8RHD=t3luan$VxK|lLEp}?Qn^p@umFyjSo{kP zIyy8abXD1ZK=X$gj){mciO>%g#nj`7znAz2+K#55VfMUj$hD{zyy7Gn7B~HHKDGX$qB@a z9C%K9M6(oGOh6?}?KR{$N^{Pu&8i&VzZ23bw?%!J)x07K=anTkU9nly)5;$*NR(1* zIEoSX%^ zSGDH6{yLgyJEgWsX)ynGUQBx;8<;-o*RX8{|CYahM(xLxVt0m0gH;2j@lG@{7(_ht zy>b+jmDMLLC&wP_^DR2ss$gYLTvfo`RFSx1(^OjB51=tL)4Ir{p~9aA_B}-n^q+f8 zuq&)_zY+G&&6rIzO?g^|=ut}dFX>`2sAjBWH-CR$Y*x+P2j9sAS#o>9%s`Opo22qW ztz&mt-sIRYP)`0a#jM3|(9#1tG(DDTgv%Z}#3Pq)2N5>Qw}{!i=oPvz14qZX@7fe&G5mi{$qk*_1uX&;s;>%-|`k+Q_UzN$sF_+{i$cM{b=B4 zPWw|iz4N6Go1`_!kl)J!RuRN_s?il9kSjkBf+xPpOCCuEi@=wbRh@eti(05F8{2FRDaXnf4nepwn z0=`Ehx|tp#De>d&nGLSfr^oZWHpicP$E|V1ftg@57i}>l{Ss93TN5L|{LD(E5ef8t z^ruKQcaun#8~sq&LgLv6S`;+bV!XO9vqueBik3WQ%i11H7~-!)Gj^GQ4C3hsGr(J{ zfsH&}i$K{{WO&Z~aX-PafvzmAC9S$#gm>0!jJ!tkL7=!r^~%;Psx5N|y+_5jOL<D`k`@wmnCt?5WU2B{Q&`^Z|dG? zR|4u9fuH}^i#_1doDc=bhPVNj`)~d1|8=qd^wK3N{G-dT4CpdQV(X1T7?Q(Uf??;J zx6yjwo2Eu7kH?YCN=N2>@Q%r#PMhF!KM!w?^G_G-PJ{?c|K%+|EY2IL#b@nJyxJP#XW2C?+og!h_-0I( z0nsVGM-E{(tj=o$*44RLgi%W?3NNvD2XeQwV-K3DiX=%e$(5%uY(t42IK~_Z_p>jB z#3+8!^u%SKPzVhr!Kwqq96sBg_HTkfkV9eHqlHlJ8HdPcjNr9|1|%lYo9I5@T7Bt@ zN0`}xjN3PV-9v!m<9seVICH>31h z*Uj#+`fmP5_%f5(9(^H`TBTmyaM9=xBYiM@9l1vzmihh(rZiL8?zxNHo7~tZIki;! zCDX%u2N+j(mA{_v!t0zoBp{(d2XGAjR>J+y=L?u3h}awbLu(-sK(+l%-+rNjJevax zeFnklO?^-ZI=n1TPV#pfZP)A0?+SH3aWk8v} zI4eulv%a=H@)F~ERd9izO`mBQk@6;=LOy*awylY5m4UL%e_Asoc~@AA;=-%Mg+`Mz z5x8ogq9Eq*bs_P=aRpj&uYP#ZaEh(9`SLx!+#gFo%Z%kX^jdZrg%ZJJ=7P%vAJta3 ztlC6BahC4=j+#*IsC>F}*ew$LO-`{!`usF(-HJMpQg5-nYerzSNjn!a&Jr^G@mFsI~bgx%0yrQbF2S@O{VDV&cHjsJr8&f1Np?US6CpKK#7ayH&q2 zaN`QvTXAf46;p|xH*7WMIiH9OD|;Rd7ozrbjwd2xFN1Hgx*U*%lae203bpF$9WIo2=I{_lFQlfTi`fTnqjoEXd;nKLctVxe<5FY z^78_1heW;~8GalAHwxwOt!<3~8;!Fxt}W`UJ&@#A5=q*%30|~9ENNp{>LvJ*TOxM^ z+{g-_$*AGUR#z_0C1FFin-|7SeSy;k`y<8xck3Oci8V3q&B!)_m5j|`6V0p5ZE?3$ z68G_$%HWM{+~|{Ji%X8iPsh?po&GLOB4hR@ zp>q0CF@7z?FOh{72-mO%ZC~NioDGSH#LP-WG!!@sq%x-FqX)(WDsTFL6h9rAWfwCy z%rS$8U(;bhCWug!TA{Jof@$?efirAb zKWnE1bQlmMl7M>qKPaiB_1zQz*46qBM!(;hfAE_U6??7o0TT`Y;s0E}U4GY#pH7LQ zymEmUtuUCUl9b*jyjI;HDYESSB?^Q{K2c-?<>A(2nkm}O-z*T!w>D5rQi7_kbui7{ zpd5rSL7eKkUC0Rqw9Y!h>B`Srj(j1IzcNyYEE3&?^xS+dsxCdeLoBwKq&Sr@n7mTAczdb&#OgGEdtAYH}0nlag93eN-q z*i99KprBlw%1shJ?uq+s3FTQq!!#=(o0LPGC}2R+&c27&@dogJjB8t2mm}RSK6b6l zeN<*pY??_f&>v>6Q1+QIG_toO^Ee9PTm%1g|+ItT3ot($g2 z#Mf0tltJ;nw|)?Q?U1=pooyz>1%Era-){_6PIz7UF}Z`PX}u&X{@NkMdW|za1?w^6 zsL2{EcXQ4vpq{o}^5+FW!{Crmk+Zu6~|oAd%xV@)Y7G z>s(Ts(K+s*qtA7n@=_tU#v`L@lE85t!ejJhG$Jo#G-V`N_1{$%n3J>jKstgk*OTuo z9Pf#V7+jtA?gJ)a)X@bOEm33yIh-7vE;hD!P#PSXYE$zLS!7A0*nFVj8)`gHBDps_ zeVH`f?}5yN6R3!g2V?#sK-#-9w+!thI9hN~W~7Zxi3zGvsM12HE!ZlbD8`>pD&MbT z5=6~Hr3qfY7WsN~o_vgr=v=}Cm~8g$Q4&2l1;9DabnV0Okezc6+cAl=O~DHb=a@-r zC<2QJXtCXxu&h5i#wH?)+9n1C(EAoSgOQ&@k%+Cu2Bn;7mW#wG&LNy;YH4LoQpst& zY%9jEoX#_;VK}s0(td0^E$K9Sr14cYP2dc3iT=0_T4}8Y9_c&aPUC%6jam-u;pqtB z4)+3mH~+OCy;E&&i?PY`97})?ae+wqctwde@qs^4^f+(IqUm|tzi3#S!56Wky}$_R zuJnbkV2x+OtUDw-6lVx5sqp)TO6>+{$3#`x@`&!&iWh5k+{~>%zd2Zj;!J^n_eK%G zjQCrBj(;UIe}s!7VE59&*zCX7g_WhF*8xI>r>d|qLg#_1*3}z%%4tsNU~y-CNho)y zGYbHr!gy%$N-OHu-)bpI`32$Dba7Hs6CSsR{gE*^wIcM+nPbog;8tdX=q^LnG7x4~ z`=oDkVb7%E3r!45{ad^81&uSON~TsFS7Sf#mPVYz*9`1#D>f=bSjQ3Icx~84Wu5Qt z2`2HSD))EX_Ow=5p6e%FP%gXKPaS8gxa~UWbobGGH?gp6H^x1otdFnurP^extB_m# z+L1xIq00x#L|n%TC=ee+O9DU+T{*|zEdy!L_s=B)2kn5n1mW_ke9NI)Y^XVh2XdI3 z91H^9t|3Grox%yJ1p}R8=QwoV=3bviDP_O;=c=8xps_Ifje0cDD`+fP<=&<3^yGcL z4{@IOIVPYBCf6pHfP;K0;o4;EQ(U2f8vM;z^nD2j(oOIBWe4-tpbl3PTM~*{1cI4} zXH+C$ITwg12=tqBDll>JIXR;NVzi1)!|JiGvTxxWWsSi)RD}j~0m2qEI(c;}COLsp z*mZ}ma*y6@PHk9g8c{q9%LgIIk8mqR1M->Xur$UDx{d?pLNoZgnW=RZcLTDSQq)V` z!DaF;%>KyIo6Z}x9+_V!TWQ3B8RLf6lI3Tm%*9D|410=J`MVLb;hT*xXDy50VyBc+ z!Azn76U0gQQkrjL7ajrXT)B`Wzo~=1@9yJqww;h1K>$wiMI5_jJ{H6 zFyaJ}erY=uV;DN&7f>0~)K@ZTk8F3FTh$G7itX|hKg z9&X`STR8t(9lUyUkk`#q-8eh1r&@Tsn!dU*yy^+upB}t?yL@T#>#^#v-jn0Qw&3Z= zh>H`ZE8;e7OoN>*=ot0pW&I^vUp_Ty&1z;yOGy|&VcpKHK&3&YD(|-upRXcU9ziwJ zmn3RWd&rW7;#X_nFC3+cQryl;#$%iAX~EC}rn3?*UYIZ2FO2P@Ny@7X1$8>Rm)(}a zEVd;;hS9&5#3aDj|;li{ln z{`c)y86y|jZ{|h@j(@b55*7bl20-l+;!ILaOjX{ufav%D3d`h^O@uU_i9G7{Wu~q6 zEDa@HEEB-p+~jZ~DBO<@DMFjER!}}iTdixTvUZT7CjklUMceLv-_5=gkV#T`?@8Hp z8fsbWwZx0m=OQg)H}=0ClhVqq^v${ZH~T_y_RSvi=>tS(7n*x1nk5}gCV~TXWvmu0 zLtu0$9tT(2O}`w^*xxIkywYy6J&y!_mGm3NJWF zXJ0UksTJ&{pDLuq#jRr}JgtTWGht7|c_zsk%UX(!SEbq^!Fw!nvtY3Bd;=bLujBZx z@2lyVRLOP3=>8+fh6Z$3L6#;qO&@6U z?56C@S;t?pP-cJ!!~`I+xc;-o{y$St2N|1x%R-g^MXHe0EVuwvD%=fN8hV|C(%Jv? zb&{~JBOK|Djzbw9bzc`k)MO9l<}UaNK8Py`Y%s2*M0{un6V5^tnRyAXU^Kw}-ArDa zG_(T8fai4xtO(jEH4mUbpDa?mEYiSYCj0B4y`?tqQ+gG)I{`bu89B3&roPfIEx@Umpz# z6BX#!G+n9#ae-HaBRf-6ZH8o6iLiPr$>6B)r1%ad&=_6yfELlX*X!8pk7KP|Llp3V z>85EZgK(1g0}g{LL(#YL#*W%KGEE+nY&!YA181uPCk`58pz&?bQmjA1^t43L5wfL! zu_;jdLxg~Ztj!|=s@dLQ%982anGL} zZ#?-rJ8`l})tgsjm;9?G-Py7>xwWG8T%GT2KbSMQb)^YNaf&+Y?Bk0v?QBO}M{nvx z1Z)csm(utD;(dl&`T5-ta7l~-&7!}xL;hE8C1zu3_+OOMO2vPhdI^j^XQuxUR4N%0 z?&VfiZd8}uwOabE4htFLeHmdDm+*N&h-O@4I;%C4Ls7CZ0S5F4Lol%<>F1G-itFX; z%^+cfqU3dZ>>;7JqcRu4PI5@IaT>JM!0xv8j{(B|8|BDLkYY?I z(PD(Ys?1sQdtUZrFJHSzxBBbJ(024?{KWb|;}6+Wv9BU+&B;CZ8S|NONFZV*^hs4d z?&C%T-$D`1mE5apKY8Y?BmN}iUkrd`3P6?ydL&sxUr&}?p~WSe1#0MYkfa8Et2?OS zox(c9pgE0*LCjlr7O)cFKe67#0Uk^QRaYG|V-1Aus{yfGX4)l|259T^Cdj#G5S%A4 zEa~$}f8<8CNKu)E);T7(64*F#Cfz+G24(Km)XDS8eb3mV(r;GhkUC&M#Y_PFJHJbT zV=UOdw=({x%L20!vXH2dFU)MX4Su~9v!qdtRyes4Wp`62!_MwPB|mX92^duOMTx|@ zIr|ii8?>Ew&GK0Nz)P_&ORtU2W9P@uSvwr^RFiv9S8+OVhCq zf+9$TPhz2S>2R}=U-J1Fh5GLZ++@7|Wi*w%V*&TvCeTCE&=gDr5awF?(7HbhUVvCfZ8(-dmYM=~e!X$YR&O+ArI6yRzUQ zZePk@99m|b0@ZHyY9f+?^r^j_8-%uOq$>6YJ~-amsgf!NO%?3kD+l^ zP1~~j5J}}+T<#cwgnZwzzPEx(;CotvSb*}_Opy{tnn95PmAgACwJEHX1d(K|_3nMg z57=9Z#Tvy-T{qR#OB8Mj1$x!yy32|q$+%ykKt497whHnvr~}6;2cZxQf_HdkL*{C- zc*m7zPNZZwtlJ5Bk5*EUH8Va%3N|#|cV4vG6z{Gae;pg%x2`6@lG^m+hUqt83}fRC z?UK|<{hVeDIz??e0?y#C$8jeOlya~5=JrivM(Im>?_4SW7vM;fpht5(idjy%^)hsH zKWM8I@fIa8GA)>*Sqij_yw|{}`rD&VOLE$+V-mEVj`Irh5&T*pM?o(~Y6Zhk6Z+eb zm8`_pX`DN;RmT$EM!22&Yw#KNK3EW-82jbZl378^ORGDC#pW+Vhc57{Ju*y_iK5k$ z)vU~L=b%e@IF(6x_0Z?@ik49AuAiirhw)vq)Ehc@kB{C-Ec8o;uY8YA?(VUzk3Z?Q z^#gUE_w$}-w=dUdL)KW3R<#%o*;GcwzdexFStSF5JX6h_^#i2bYRe#}@*OJI8 z#3jyse2?2>|AM1$K(|})a&fou-32WS4d4o|&KMi77CQ=?)UasW=&h$hi`Ldi^zc1$ zkTA^f_YeY!Z3J3L@{b{e`CwIpT5P~6G8l?18UG{G zq2_Cl+}^*>t2ytcU)`xvd{PzM5N-N<{8o6(@g3D^n`l61O{ zTB*XH-LIp-UOH;G>ex*3H3>jm=GdpXU+D#6U%d4X<42^z+F-ud5c>f+EyV1FxY_m~ zl+QNO`FiQ8qb)o-Y6j=Z)8{-Fk7AvDTSCymK?Ku)sqeg;hlibJ8Oo3Nk&_SZoUe4% zxiIyNdlU4vC4d&cc{3<#8NYe45mbjz2C)4X`A@dxkB(1t-!)am(%9=zisO zow-YQVwd;zfwNPJmh75aM#s~V>pe4RLa;JnlTzh$Arjkecn*aT3)=5AXM9orOGgOb zU%=jZqt#ax5L-h4z?b+BV@ur7$lB2i(EhQPwU@Iuv-(3xT*=M$pK9W9|FrOY1DLl7 zC?p5uW6o2u?D#NSg%`-nC-VOp`S6F~^IDNWa)|D2xsD)D*Kk#Gg)S2d|AC(W?i71N9 z7&TCU;B|&Y7io#UaS3(@)kUZ5M0kYtj`$b{B@X^o`Bt+pjFnKF_=4yX2Xt!V%V zaErNp3kM@&7Uz}g&lEVGaWkfxjG^SIR3YjVUeWwo7b^}3F3xp=)S91*kH+&e^*gG| zE+8&v!a6lf^^tU$mF1|`IxRY55--8ggS)Wfb3wTaL}(>5rr0c5i6{rzu#JGg9N3y!0p#trW%{ zdl2-TgN&}KCU>-QR0_iM^?lwcQ#`M@V-MB{-HdD^B#IQq66QwaOohqPFtEr2&ijS6 z2y^`gjo_1gk#hQ5t3Lt)H2|xF;KLIIK5&Q87wgqyESWt~XvhSOtzk`+tUsw~T~uq$ zzcWqB+MhdVvC-DrlD0c+Jig!`$GajJ<|8?YP>O#g_p55))J?9KflOSAZfXD+$>+|N zo@V>j4qP}9H4o5()Dd5b5VpYgWnnHvmJ~f@KQC2QL{N}L{9xv2dl_&vjy@gZ<6OA8 zl!3l3#~bc=d}aNfwMCrwNQ1*Hfqw0X|HIv@^XF!5ya;x8Krg2{7|2aNHhlgLcZmPb z{2f-&6TEJ#Eb!?aOU|sJ)72Y_kfnU1x)j(EU3qcLEP3S@QjX4i(UJU5t(iUtBKswg z;rgauN##0#4&v0gY;%en6@DZPOPP_d$HO#F=dMKsd@HK((wM-tt>ywb!Kg-_BmF2I zjADYA43Au=yAI^?S!LLSS}y5YxbA;}`*Vb3F-R?g0WLQtAVPTl!wW8ACunA^Z|^3f z|6gW-idK?){D|*ax(s)(a^cqAKA+Dw4ssyO&E^q;L!{!x+nnoh9);m{yPPaV@^hF|eu}_}R-j)SUsBaB&{Oawyvw7@V|sLFl7mfQ6}+g+ zPh;)S_3hCtsRmLH`j%cD_~yjsHzO+a0D?^ngxbWq90hZHnq#FUh`YHUEQpT5~kD)xrutD4E7>>@lNNdtV-kMa6%O)aCO%g1JnYnTlm4+lvhXVc8z)h6bd zp2#@yriYfzlBPB}njOr$EsS%Q*E&qE%>w2Npd_mxzUa_$;XC;0%5L#ZdZ0u;JY;$P zwZpgruu%peknsN@zJx3R-sz%7j{g>4;{a9!V#g^J`baMV`&}m#Y+bd-!PUeQiHg9#~`~2fcQE11^P#@RFVCp`l5nvOc6-}cS0#B8LGJJGWSch;(zkIMt0O(dMNXOgPCt3i(n!AA*CHUh8jvpL(<4%fqyo$>`Vmq$gH)K z0wZTOxo?oYwLpTd*tGbjiv8g`kab}Sl9Ub$d1X~ALx(k6T1NI;x!jM1DXhFEP+_NA z^*zrlg2=*=E3NZ%{#0%~EF5_?>>n*QV$a~`_{vEaF)C-&KWuuyYu59Q3wWnmaOm{u z@fu#F+rie`Qoy?1bj17u!;BL3qA|I(`YDJu2AwzV=Sx4ZI}N1l%z$#wd~0?1oP!`} z9(M@r@0`PAr_jJ4tDa39zi;>4toXiE2|+7P^YIW(Ujlk-h_+2?odMC)y(72n%m|Mr zvSERIhrR3OSW?@HE?&(o9`Jp7von?ir~2M0iDLr=~)obwc+cJ zwBt24e{C&FT+1#O0zwK55K_GVA!PlRRo)*D+aFbErDE;xnA*5UgK)Hq2w08Ji-|S= z8PivLkgI50B!g@bYA8nOr}wnwVQx7p4ofD)dh&F^v)N7-ZtoA~YZn+pG78uFLtnbm zE?r2#RoN6a^2_yto)eC6Sv@)_4cn3bV9Lr^<9zL+z9Y?@K< zrBY7vSs_z6?)Y2o%x<83sDz*-0>uaD0aZLzPyP##`0T?#BU|dWm+2N#uYfO_xdpIG z8#6cXUaOKhQ#zwwg~rp}!Fb%^k1y`H%S!pieB0}Y%jGs<;BVb@T{;Ielr~M3y{sec7(Z?EXaLbQ=m|eCnOBc%IoDC=X5=$T}5bv=1 z$T_0ycT0ny^a;m$8r}!Kh!WvoD)E1c=xuaHQW;Y50ul4S2{wAA@&n0!` zF7nXra7Gy;iA5~l6|uo5qz&mBGE5Zxjk?E0&Kyx{32D5;mUY{OaG->b1q_V!4D+!m z|An7C5!nyCHoY}f3=#I`zP{Kii41l&iZ)AI)^jl-;ienDwfKyOc-}#Ufoky1o1JYQ z*$!cBIpQB|Z_?85JqxnIQhU9pT`I;p=KHiQyJS1C=FVMu!_DC(#VbB6?qH>3j1S-1 z%D_~zjErW`t<+qB&I`2b@7u>*DQER-fnY@r%w{Sg;7v`xF8@y7m)a zIcp{oC-z7vo1TF)1yMeCn}F@Ifb(NL4b~7-O9~!k$us`A?Up{tWn6hI< zxpZZ-qY?D3BVfdZiXJCKW*4CR1-*G#- zyMKK4;9idr(~8}N4OC`n{o5A(xh9)qnVbMkiA=c>W1Abo+u8&yNiQ#1)9YWFz9?X9 ztg`_4VgkUI>VF7dUu_%}jcoPp0n&wr|0=H>{-^rtH+Sd17=&?Pq3*iDz1pWh90ile zk2Q+DD-o5#Nm}YMCZN9_<(+X|&aoSO5C-N^vY(!`zSRvz^sGn`bC77(;e>^>QUIH&`8LnhWMm~7iS;?)R| zD6RxcoLH60nNNTCjP8n7D&59YwZbz9Qx9XV6 z)K*g$BXikL2048wP~MBu$v>O!<+4YlchD>(v}9e4}@c4A&gSqj|Fk$kny zt)Y6iI}XV9tH_7x_fJS48eb6}%T0l+X9gE<%<%_jZ+ct+e|oM<_7(Ts(;*qp_a)&z zjR1@&ePFdGV0)-V`SRSd=D`T_A$a>QQRG91_s9*1qKyATVg4@+{GS3RGIrY9@3*fo z_aJenn!z%}m0x4Su>eU(aMnZ%-Z8qGt-2-b^#<1|0lk%hJ5JZzq$d*r$rvh%Umvlc zSB%uCCG6pya?0K35D5}&D=RTeiwTje;+r~pbY8pQ&qA4y3vD%~%DIDzM5h@Ig^#n+ zv?C+>*IfncdS8=%`#lE=7Xkd9ar4DTnkKTBT@u?hs81RXw2yGQyjLzgW`aW`gwWbm zeB`hbsmh%};Xx)RxswU7`4l+=MGI%oOk{Kj#=qDja*s^jOuv^;v5HO(*)9)#*c$8E z$?MrGxc1H5w*Tbmj?91jf{8?9a(&9&^7yI<-FbMT8uCN~t1>Q3@1twZ9yK&i2%iV? z*kpH?CLW}GFSxWpTJVC|bKBJZSYW59UhM{Qg;s6KN`6e4&28u+FZrPChA2ZyI+&+V zWVix`If_6UI1n;eG{zz-9Ol98;&ewQY6jP(Jzn%*MRAos27u!!+)jcGYAD*0e%(G- zl~tq5H##+(Qs%x4_Y>_2@h)neo6mohmnc}sbHQsk26!q%bZKGXZ=k*}ku&R0 zbSzoe8fQ#Lgx7q6NjUDfrwW|Np%w-0poDv9AZ~X#cqpH>3f8~FB@N`&#=m?;Zz8m#~_)8D#4{UvJ<(zmv;HUmh2|1L!YtPTHlgZ`02 z{yUczM(e%{-oJh!7#Bd?_E;&^GaQ`#te8e^!sPe*C~w#G;Hw7){lq^fyYI2@K+dK{ zQPYKNU%4;xD{)xkt;WlNGDJi*AopIv(`J^NIJ7GB9;gejnkY~PioEJ0potu<($tuj zGZviQ@}mTjinG`nC7c8YQF!?05Zek>r~3h@wcQ5{g~jT0;hrx&o3kGH^d`BmRsFpi<9pqHLDj zOL&x|;2Ik`J>(v$BjtXoNPE|3JojjAY|#NJ6pCzo!6T~~w-}Z2#$M{ zKdG%ZIC|n!XkQ5Pn;V^>MM1Fx8wZDzZp%<*e|&GdqOsN(rDL#=4A)sX5k95{=3N!h z%~pOonEyhP3+~qSr(i)PNai8WyE#k;vj)|Ko5X3l?}j2gG$)qr(%NxmxIOO@TACyc zmy8?&YVmj+zRi4H&r61z#n}zKXd6FGIbrl6N0W1FWeY;rRy!xjLmNL$U-K%?Dce`n zT2!xCPRfR7t21O`^CxVtY4-+#t$x6a^~mXpJzyVC`Eau4)+Mo@#Y_@py}&f9K5wzk z8vA1{0fS6_>=M+9G*z{vOZww6w(E?&r&ug!H}jKdttlOr&w~%o;(~cAxpvf1_xrcr z=P$h%ezpBF@L94r!uzkgF+yJ!zfpL&N0JFJSK?ky%hJWCn7p=Y3^P3j)1p-j8fAX1 z`1BL!2yU1jO9`Wc$q=2ebUpD6KOTDoC3Uv;{q5i8)Nz zs8Xz^Dvqh*G$68M@{ZD0AX`EE4dLF@sVe4LnOeox zlY;Ipef?FJo!t$C5dI*c3Bq$GOdlyJT2;E)*Cz++ekbOF0S9P-56X$%AAL^+PRxgu zP|#QnL_pdg4b37F9BdGq`*>G*T;UP!A8aW!rmh&m>vbE@!C5L?7`{Jw%26d?bgv=+7e)47judD>!Cw9nfZ~7d)#1rZ5Wb&VI z>_gmuoTwX#+DX#6eqb`BokdMwi2<5dh5tgWw$@KY8&^br1YM+zS|uO9NvUg0Of#uT z=Aj^&&8mCooX$>s=1vPBQSlcA)W{|bmmV2EWcu3retBK8R+g@se`axg3H{;u!3ABh zdbG6+6n<$_c?4twLei|oxD~Zc1=BERz#7gP-<4djT7WTqnpm+DC?Na)I;(cv#@_>YEIW#jWH<536oUF`g|&^^!h|y$I7N=z^=4GUldpJwRKF; z7eOd*G%VxVB`s}c=0(oHu)#S)_p>oCZ_OTDrN`1q8>TzzTD#ICgwH`(1{Be<@Yevl z>9r3+8(_6nmZ2-FT@o#vSL3_o7?R7-QxBKjmF)Cu1oldV)k5gba8t1DUM-8!-oqhs zG5ar{oe`X+5*C+wII^O8;PO*S6c+q?X8L|yx8p?>><%qnZmMe8(cK207a&cw%3%)E zQW>bFped07wfC1TFgS9Wenw(d2*y$FdGkbi1^R2g;FPTI#`@Ki0bK3x<_j4UfN%Z2 zGL2H&{N-J~(|Qh;c#x${EG~1z`d@4(KP{S5@lx8*B{|T3ja^Bz(Jwvy+3f^wuvTsf z7dGwI^YXmehU`d_3_e7gHX&a8C1Kt%}P4Y8ozlprxH+=rw&o+y;}KL5eQ?8N`#WJ^J>tlU6Hr2lH+6Qcm$W zU4{)xu8FsBf$z$h@VFOPDk8d`6J9=dS{ev~(?aDWDtKvg9{n6ai3BtO*B_?L20nU2 zv54VgQ6E616JgH`b$;3`?V;$*F&q6PwNCKcNFjy0`2>L*iR7@_dcQ*`9`DTrnukl* z^GJZV?)dWgv$ee#?{#5iNwi={T`b07Fa?N0S-eVI%8tD1qN=VBEofx#$89>W8#;wV z4p*$GK>_&ON;QZCm;y<+eud*AIH!t<43J3>W7^C>I!UOG9VPmAui;=sVYtb0D~Bh;-v3_p7CM$zr!UF=UDm|{=wjZ!_aMr>Gyr=2yia!pcR zt}Dpg$Ep{B5fJyc8t&Z-BQd=FCLsCwz3x~FkmO1M-uJg>m;e7AY8;PUKRtZN!)tf~ z056{2MJ>Sm=@Wb~y|W;i69jE^7AGu<;Om3#SGAs?cJ=!+F}JHOwSo;p34I-kgOGz{ z?cLgZxU*(70p@b%V=b}0E)gDRAeF@>5BC8a$f#mu^T;2^Ni2JVW6gy77CfEfgXx^q z>&wn~(xXhnExv|fi;|aD0~qb`uSri%&+Angn$&9>4a**Vw{XvIAD-z0*2*M3nuw0y zfhSRwZl@$CMb`2zt z=*}J5*dk!&#MaAfb3^eM|p=IfY| z1lG}Q1in>*26PnJ)2#k1T7P2F?Z>SfBolwu1oJ8=^vH(qt0%?8SjSbqDM}zXwa!|z zKJ_;)8vg4IqQ0Qp;d>K8ld-_8aMA=Co)%er`ehP^Q(UI`u1BEk(tnEAs6Hlt5g`Ji_(?rsVv4sl?dq)PqK8f$zh3sXy* z3l^1&zsn|qO2dH%JQnMLTB%)fwz~_oSqs{4ZF{w!Kzu-1_(v zj_}9hI$_-spd1o%^#fVRaUb181Ww*ud!IR(0JKHa6>%+tUN@>TilnN&!x4h?YD)v} zAQp9=Dk{V-`lof2W3UvEO)_8vtoDm<`?h52Vh>)CjM6?7`?#p@fC5}z+2n8?WQ7c( zD&?V_`&&0XCQ6{|729hQlTta z0ya;ZRu-Wsh18av5z1j>OZ4Fw&#JgMBA0Ax6vRpdfhZdvfitG4XOY0-sglCd@O+>c z)6uZ@rQ?IN%elIM+k4aSonWx9iQJd)4u%-ZJnN54D3u<)P!+5t?)tc1svG3fS9|2; z;yb4f2GxxWJCETFvr8Ie0A2uZD})|O54C&bk9XekA+=Yj5@m6@^nGm4GzjB!W;H5`|B;c$L@;i z#+2!S3wARjFL}z@kc``v@CZ=VVVKf3u#~MU?vw%>lr1=DI2S91WB^;5=$f?F2^-z- zkgd}QiZ8$J9!>+Q{oh@2OV~P_INBOm1ANBj4_{GQx5Q$A_t~yNk4NKT*VKdzCWXmp zrY($JSdq<>GpNkkRH;mAj%ST#cz=jqT4p7=vmwUG;xMCy8RJL>UP=;F1#Al-Ls@7l zGp=ZZ)Qb9MI1zg^7tkc~Plwt+#5@KG7Eplvq4D=k*L=hj%68Mds3gb>~91a zxqr-OKva>W-3^nW4T%Z zyLPyO!5?caz_Y+iJ_uOe;X)Q!d^jd35yTkV*V50Hii}Ju*xQ#t5!~l1w6HBg18^XT z3#;bM2bE5-;(2|%%Y9ByCSMvMn=Ye|u7o4yT5i@8D(v`di7tYCO9e-#UO#Y;qJI#g zRq8~vhpCXJVzOhd&y>rG;c9lUwtyK6Y!p>QYQ^jt&1#aYLQlj+&(-Or5Jy%FoPKOUc5*>R$mU)_52ySh@nnAltmgqI&a&owel zfvp-eyXw4SMl@-X_523FVqUKti2*q86kyl&cgGc?F4oo_3N8lLzd%^Ve~v4Pl(*%u z7@z^TTZ6trpnQ%C6Y&`plS*;vz`AB`Y4E(esb$Y*5w1WH8%+9bg3geYp%4-{aJf7VVPqOp1QtIk0P`DzT0zD&Lm7Y5FCiFxi zIc?vAz2f5izfYM9-on!UWExKg_bMPBU#AK<9 zbKFR`&@S1-5s|nI$QuL^GPw6V*(0_6>mqOyBd|Ynhm-QEy)HfzuWaa~i*aSy0f$~G zcgGI}HNcU_ihs?E4OR9}g~7MyipMFQDs`Pb;Ti9gKaO4&L*=@)wT_P^o6r79Tfsz< zW#lwp28Ef!u!iaC<>u7_qVu`)1C!;6W+PFzzxKm&xc?l%YDkjAZ(D|<1`+u)skx8{xVTS+FaX#x?0YVp(|LG%qSdnX_~;& zes)p+u$+zXmQk@gXkynht3#XA^|WM)G@!TK^^zfQ1+SZ_n{zKm=QW_~D^LgcwA*_t zMLKx-J=Tu{mlFp0b>fQ*`S+ZP(@>!K*xz+}Q}#sdG68ko3Q*_&;|1*BrnLVvmHod4 z0E&O^!>mJ@N04)eo5(j@Y-feqdmR|gm1|k|OOq+&l9xe5-@D?CxK=rVI~3%uPQtt^ z>1pW6W=PRaLgoS{*7PN6){sBpTc$Cs0ZRO8ZaX-ThU%KSd!HUTvLkJ*hE}6u!(;h; zF>!OEPUe9~I5*9zs&hJef(y6W8<|a6l5|VSC`5YZ`N)&mL+F?rjp}5Bi|<>r>)Uk6 z{D)$AC6iLuY8L#3CGn{~+nInnek{sS5bwB1)0dsCwaE`2epj18&;{*_#pks33VS)- z3hK*l##~u`#zKMq9IP@tHg}2Vk^v#BWsIfI)?}rYFd%1Ypm)~aVKJ)e6kPSQAiz9d z>)XRW8);CK^TovGRj^9CEK#7XU%H7M4&OTYuIWtiG^ho?3Fp8DQpatQ?+&!e=Xk}S{+)l-Ogydh}Q6E+iQopzbSrAZP0OkGeitil}VcKn^QTUS^D z`6|;D+ISLXgK~;T}X_9nJB(ExkOb=W- z$s(A}9V`G>-Ru`vy*2(^lEekTRrhR8fdb~Bwv=3hiyl#*$_A{pB(Dos;lxUv7-?>g z?m7}O(xc8+Rw^ITvVOL%|Hy^%f#7yYG0kjb@mIVJzR3_`n!vn!vUjdRcI8Tw`^yKyqL-PWWPfnJ#vS*ZMeUL_e zt=E30`oesm*S(@wze+vSXnMP9;&vUAix1MIU{uH12@Bivy}fJd`#Pk?9WrRcDEo0A z9m{#lbBh3Sr0V^8^U#!|I@B!pN@;b^-PDj-Sa11hUoTJfXk;6f`@;}sqKoys-?WW( zmVw}mn+mTZlUfr5ThFcIq0etstfar8*gQ4>UzkVqOc@VA9p0QDZ>^z;2)#Mb4qJ%;Ad4*_nOo@<45XK?NQ{ zA=FZ8CTMX~pOf2X#lff4Fu!Xex=}4?48-79 zssrnHq1$eWsA`T04cxKjF267^u_cAU%ldkHAuJxzqgo6c$ugF<=0@4%xp5kS;@Wav zA=}qh!U$Lnc>G&?LftKu0IXnLz4PS*v}9F;hN63-R93g$tJ0ng4GPlC%7Bdlq@euH)%>!i|X~sV!(j)~Krp zj6Ociep|fX6Fvc*vN#67Ep`BOqQ5&4`O8!LkM>+y;g8;?rgjHJeiQ;X1h|sYX!9#G zdEob2vczxRT{9gA=?7~nDnDP&JFK9JguJBAr{ArQBB08K9E0>X#Y>SF(RKEWqnXZz zr~)Pr^m$(t>6bXi+VSePs{>G((!)%!Dzgque&o0 z5Mv7}0ANrrZHgCPjjs9I5kgo@%^ot4+-Pve4RSSKAb#NC;56-kR~OZZQloIrlI4Nw-K60aN=@KkqZvKhLrny7!G8!JPKy1_9*V#SeDZKm9wgCaeVnVl5q z$^*I(xP-PGsDN^h$I~IB=`NFfdVmQ`q>CE6RfZQJoBelNr+Bi$RFF>aAauZc&&Xn-a2I0p)+pEjxCKQSQhaOOkXLxt zjbD*0;k<%qo?uWcWLbu!`h~R;#kRxVRTwX+K)mkQoL=>VUDE!k7!z&r;tqLn8fJp{ zbzfagzU8<2_vu%%6nf&YVP^Jkx!oi!9`yUXPUWjZ)-h5dsi)IwPq6Dd#B5)Qg-t1Q z>O)czz%n}ft4TLWa4yv$lPXpvr!!0vrG&^=^ym)vK|jS%L1{0ej=?vzX9RDYR;L{F zEwv-V$+-n)tZx}qXk85j4pxBBfc9K@P0Ph}v353W>G5c9-h+09k_`U(bUp}|Ct?!! z`hgeIS@+qYNb1jduPf*3PhmCrRV1>`A{>Qlc@BE4NlzmhWH^;U;U5>3V@FjoX)IG(ByV{vWlb-;@rVQ-rY zH2!=JQe~{~v&Str)0M`At2#Wo+Ly{gYcboi+I+TsR~&pxKu!iADk}tB@I>nChdds` zypSPX2;{ByXQc`T3r5q!8%ti_N$C`j%`L1>SRF*NJ-h*HmO1jYrj}8P_5kncr=z<8 z3Tc|9$swnjX|3#^w%pPB&=wR{J8*gTvZp}aVeioA3ZvMtb@85ND3UNt3!>xDi%8=D zzz6^B5Af34YD)4Rx>s73c2;Gcj-rI5J4ZPKn_7-H4vK4V{f-=XOdiNoFMDI0#m>|j zWjSy;VA)c^9ogbz?B;}d1xp!N#$Xp7|CV^{vm{{1F0;&%GZu5wj-zPNc@ZBiF=t4SSd6i37As!cw96Wb> z+lBO9Mb&p{!$YY>9dcr3RTRIT9#Uk{#ZN1EM-Luf(`FF9)k*8>EsX-d3#PzTgo?zI zRuC=UKcVB`M(MdhrNNE2*2`t8P82n-+T+3B>azQ$&JI^Tj z$yb~WEC8GzTeJTs;q5jhtCWBJyno8kB*n|w z0dP)(SKi?go^_(jUS0Z>55Om9-6rz$(=@4 zj!*mZM~=;|71OPhxnpM3FlwZM#5euKPlBYknJ*F?U8J&L>;{T6pK?J}z-PFNAdXWl zaTIX}F}(v&Q_7biXG_@BBZLBI;aUQVQTt~~pQgQ!eE zMohGhh+6e!A|iT2wsJsj@?a#eeR7gVF4Xp3IxBIuw`fDKz2R(&S29UMm%QC-Nx}r)yRP)h!zd7YZ`P*1YwLG zQjgKqBH~hAB*BoIuPEp&%?(NRrafk7Af4v!eoJ6&3|7q<9))Pnd<}83f4rzl({v>t zXuoz_$|63qkb{i?vneJ!$$p$kBOQiOV<}I7j64l9vjba|C?}0>%+FS7ZPeCo)&$a= zAz+Q6gdFi8zfZpRc^-fj03V#56Qzi-n>k0)ks%vRqjEj6}Y=G3g4#M)EAK6If7*H zQV6&*s&RsA>~4O8y#MbcjQ8)7u&E;eo#tle`2W5mLj0fq{r^n63WFGpga9wX04Tb! z|CisPY~W~S;w)`v1P}tVv;9LedAWxD&croV{@4g>+CJQazm|rE(`P1vx_~r8DvfE05PhX_BTd|$=jlcVDWhVJ8kTdK3 zWJcF4%|i1Y;e7~(GNM}X7+WkdBbNL4Zfl)!h*GK`Q30QH;#`I~HlfvhYYK-B&ODKjc&KFI6Csf1|W5>}wx?Y&}Y z8vqeTl{lcV4#woBWkv&z5GWhnFV(U9F&uhW@}igWa`IkJm(Q4yxC7N0I&As zqg>7+016U$HqSl$`UKCSASv^3WOxVMT{p&L8{GpLOnYZZ7OT7#mMr>^iIlqzvrz<7 zaQ|ao7eq<)zPCC&KDQF|Rf)vu?J3^GyY77wNV;s+nnYE@= z3VdrGgZ!hcW0Ru(N2}<#41^J4=XOwN!eEw5f}%IMTRt7~WsNiPpwD2XIp$;|SI>nn z6hY}+TF^z=5k!Ygd*bs}Z7j_*$56+b1hilJO{hXy+^Xe&p7A4(Hj2=pVeOV-_~cfM zMc^{>t~6&WtO(;$Cox~GvmGl*Ci00|xz09p0dK`V6thol4gn+4JquK{p+EC!3*HgS zV1M-u^`G;5OMb8AyLv3W4mebB^gfe-MvMvJnGiVPfDsDIiW*W$36L*NpHnzZKAdws z5%Wx?7v;t3)5lJ`rpJV|-JgjeyN(^25ByzDW6RvOU0{&y?l9K{jnnE z!L4FlFM0laXR40F?$Y>htI~FR+eeZ&%haYNS*?~nekr9CVyY4%2E(t?N}Wf8rVz8G zNy5kXo4iH8etDy2wwHu8a%+MQRM|ddoj>ocPwuC=9N#`r8?l5Fm*(krkiYJtWw){u zbpSO~6|e#Lx9h9_3H^V>?!Siqj)1+Dv;|;=Wnlf!;7k06mQu*o8?vxl0&?2z2OLl^ zbv9tB`N|)(AqME^Y0XU|@l>Ou0line&$0UE;EtD4MaEGkv=@SpGb2T^T>6-``SXb5 z7%r!6&z>;@#wr>eY}Nr?!1)7nD?bXaPuB2!=!*foi#8}(0|eRalM#1VNz84|O$$iG znB}MfyhL*o1!RD)3UJ4V+#)D#uS}%MR#q@lo>;@uAq4lSJ^W!7JSW>%eh%RKPtQ>z zW#+()JoxS_vZ9ylx1B+@)V`hp~})fTP3~a`;`bb6YC-w z`t5Dd+5=wixW=qLIDm*n0oRd!H9tB*wlj5lT&?V%{gbX*$LBHyY7d3{g^<(sNXmX| zihx0p`~BSzdLWX+0q8s$0KUujU)Bp@6H@~hYv=#%zA8?C0QiCd=TZUaiJ+^` z;XFWKw;z;k$_0yXH9tazmY*6pu=Wjpt@h0YTuW`5PZq|WOYptFH8w>KG>ky;Z$?4G z0`!1IgE%;io8Mg@Fyv*>6SxYhLg6-u)YR3m&osU66qjG$>$C10m1z2-E#*Y`*pw1$ zU(HMLwButodbYdtovI4i?*};6!o8)raih>9^(6)KY)oei{f5XTK-^(?pM&xTwcDLT zf~aG5*nrCfH6-gTYDs(Z&2>qi*PaM3*H=_lK6UN z!)V+m=+9Wh9o5{jGZ^3~j2JJ}lR$>=N%3A%6lOW#Ulz|Jd zhz?*G&iG$iMakL4P}IWO%QdjGVHCvNq?aJr}AdsUel2 zj;7)GBaRvSVY{O~>+upY4?ci8%GJzNj3yk%7NT+;HJ`MOsKsGrrmtOxq58Af!uTKe z?YuUO@@B1}n1?{2$I|!K!dGG;h*QuU*wPWLeXLIyucLwX-GAiNYE>k$>w?zI+ECQS z4_YVpL2qH8%lZ3)Q(fB`T6|TV4~W)+(f<%Nu>rTQ4P1 z2A)j-Hc?DK;$3tn4?aYEa8%Q8e^u{o2Z)_nd0pos@qzW%hnN#X6P>JiSd!-QaGGXwtLw7b2;@H6y^w57eY*W+S+LXOrF=CH0_q0 zLv#SGwm{oDE@|IsWXwsJjILjE!{?>_{qfK=J;{fWOiov^{JVvUPZ4e$#L!gL>Bk8HRm(gz#F3Bb_(7PksBXc15&8sfhq`KrX=J z{_Ru!x7sCX;A$Y^ZVx!`;{@m#|Cs732>kK(K%sK5pxWilO~GeD#7B|GnleALMx6f& z+bo1d@IKYXy0DioZQ2yb z)ZR?rJ6J#O_FTjo2!^u{)h|{_iZo`qx1C@u4@!nM`Y}0?)^kNoQ^nVacPcoXa1T}T5j4fbp;W;UZPFLD^2Gh9A${g(={N)rPzq; z^6`OC{J`GS)r~xGmFg0_akEH6VwGyO-%te1MsI%iLM_TMn>e3w%@Z)~lO`$G3752p z(KSz^eOZ3e*vOhX4Nok2<-XKa^s~VfI`Wr0zK3WE>@+571?T2tD{P%vI=Lk7u)3&zT%vB__zt`}JX`Ib4c ztM9IoEy$K`uHMF4B*opl(qNIt@nADgBcRLHlAWytK|$hGVC!&zRXw|qql>2|5%D5~ zV?rgq@@FK;KvJR1ZaU~Ru9!bleyN2rwZ~meJiDK66=Ss+6`vpvwV6-n%AR|zC39bH zvT~3<8Hb;OL>br-g6qb0)&be}oV;Olnv5TWA2OZ=Gj>Ewx;uICYPf@ICy&X-a8Aq6+!O4|~ltz28ZK zGF-Xou3tR-eDeS#B1E8VEvN&LEEv9iRiGfQg1!}?m?{*rF))Lou+@G>J5@)lW>@pl z=zm>HQnpCTuhcrf;|$MwyrzY~xYxu%LRVS6)|Iu=kV4Q!L!Xb9>}{hWc4PMphGv7_ z*1=O~k{UcZv6I$X;N1DCbnP=c*Z?2>Byk5wcM=E6$Ye0jSb9G-q0o7XW0Q@=l;*=e3{+_a9Y5Lxa%nO%YXRw*&63X!I9s$=(bg2%`qd z1YL%=HdL^8D-Rano@(#-+$gwMI}N3Sc#zQ{^Oc=Hf~y`M8-A^iNJTJ7tn>~z3AZi! zKnfK#6>1YE`zy=ZoQ9T(Gn6I*cU+xrXZ44^dAqoWo4^ql7HYRGFq`gx45unLK}2p& zf?yBQ|4+hLMgou@8(s1)Sza_&23g$Q2^I7*_@lwA9d-ExEC5Bga z0T-#9Uag2OV}aNn3+hyvlCCQdP=cBfSa$-gyBPz`TVr5+_L{6L)le74l}Y`!zuSoI zajuWk)G%Q96;sN?e#mPU_92hx7UY~@oRR$zFgxvneAB7%u9+_0un%OHik7;U)nXIZ z6f|?5gs|iQ(#P5yNA$FNuh70-@7T6H%OyTN_)xh(h1Y@iy=b=$K?JE8m+EVE0ybQ# zlB$_hZ2L|KUmim1;UhZqM<|*|)ZvApvy*x<@JSvJ8a%PD54XnV3OCk%Y>L(}=>#tM z4HjidQcxkK6eg|A*tJ?!Tby5hMte#bE~v!kn2E*bz`nmOf{)c%M^AkLQ~gX|R_ zt@bU|pW#`TPIBLc=)c6y!Z1MQJN~p=L)NDys}pG!aTIfHd;DdqB3@~~Q|H|X0;b^h zF#=Kb6=&f22No8sS2|sFywG>3zrH#8Tz-%E$V1z^RHgCEzDx?inFhXTBBx$8Ll9f3mi{&_aa$%K@(z62z zIKDmpkfWv#j-H-22xcW3mLM&N^Fydq3JB>lMA3nu}Q**M;Js4YcKJ9B?wpTle# zM>$jNFKUL;zJ!=r`%x;D-%P{&Z4hrzp9edpzBcaE4VfTj!s4Lgtz8tR+`yPdgCO+gXx5vK2Ww?>18r_x%hS%!J zmW(XO2d5?&Jdhu_k1t8N<=R0F$7)aH>Be-JsM1ZDLJpQ(?TQAI_ zLIZT{%+UXjS^96*_~$LSKP&aWj=`y}+wQaeI+F;^N`4Bgi?KTVO%ZJKgF{`$Ch1m* zhywkbx*<&*rNrPF==;M|Z2PJ#HXn1yN38>UTC*waa^xGqLh!Xhg-nA^ekQj3-XhkB z(w7H0lJ5{SsCA757)Gx*ai`)sV`t32&~;9QCW#Dtn&? zxTqD_Z(@5ak4CmDo|;VcTxj z=SYnmFdp>jBS^b6nctWysEvBmEIR?pPE7m~byg!bF;a{;S-Q?;RHhVjuFAxFtwS<| zV^DEyI1mZZ82(3&2h@X_F&uFy+%kq)%&ceNrp~!3pC+38O-T1AI!^b@ zIORrmGY#+O9#`iKA}c-w2t?1stOT7AR{9hhLpFa+^&ykjC{rw7;}r50l+`gVFJOWZ zu?K28TC&}=0|E^YF`l?TIy{6?6b}g^KodzL3Lezc{1ljSbbcL==ihl0FIglix3rvR z=gS;dd}{!61H!JfTdIaj)5XQnBO!uc|P`o{>2g zmyc@lX|TA8M>V)&jjY0^zgCs4g%2kjG3Sg*_5NT;hFqh4poie+bRaTRgyxrXHcL8R zm(NgnBS6vW%v%qlM_su!5?voOTlFZ&KGP%jBy29F#(*WrQi3I@CWmMNp=|neWXbU9 z;lYs#M1{!loJ8{KP1|;RYtLUQo0xy8l_*&_Z$_Bjr425Sn`;kAGWo&3t1k#m3@p+a zG3Y$i2uv5u-@4%uzoKc!ZGbDHYjEsSp{RR`Ojs8QK8(2s5<Su zW;ZJaY-XQp`ulZi;(IVq3)f?~_}JttW?VHGO(J4Ikf*xU0#J0i@Dg3#wW-JTQLy$Y z^_C&@Des2Y;?H+8J10G+c1oWk3DY@Abb$#H2upN(@sqqg_?;cpP6_8yx=fuNjGS$E z(P>{2cX6!Js?9HYt|!(+t{_rEmU15VdNS;Xg48ohY^88*T&GxSWfm%hF%X;JdQq}r zFd${Tg{6=6g;b=o{9R#eCMgCA^L5X#+C8VDl$A)XEu5+ma z^iJ1+wH&aA&wzZ|2wQVJ_jNNU$h&1WzQ4vA^t}E}<+QrbhD{ET{VM_4|KA?{_$}Ya zyEs}nd#Knt{0ngW&k`VD7eJ3Z3>Y}lt%^*l^7^4g5~YQTgt)JaE`0Z!nyXjT{&Le% zqk^!H*Z@Uw_4a<(g~zhbrHXH^B(F=joi_?oaV?gCgCo05lb|FhtYT%f8*zb=B#n|t zQAE=qNcCLqp_NykDud@3Cmd6x6BW}3T(!ReSld+=?Q9ycn-ue(u|kj{0U@PQpts|1 z+))ldW6~(N##(&>wF->t5kQF!R`oz5M1yUx1w#YUBD_=iROCfJFs`(vx3}(K6?CEh zSyftR)vZ6``=oxm;g}CZ_Nmg&A<)L54lDkyerAvwQ~?*BbCWjNtvP@cn+DoK#jKh! zzmX`l#2gD1M$BD-fn)m)C&RaI-k>WoeO-b%9lz?8C_3sO-LKN|gEsl;ct=l98Dx_)y(azP2?Tz%m7Ox30qSWM-yA4KPGKODl&5WzwjG?L%KkvGL2pu5bY{d zvyw@!Pyy95*|BHRh=E34Hld1n?+-X!MSA7%h&&`W84usaYeH_!R0++siaQ10Bb#e0 zhk~1@Pwr3j1`br>zpR;`?S^&LDl@7SOH*8=p=lN^r?at8#yl;Cw#I$^kU<0U8M;$Q zj@=WWx34PImx32)Hj#W>7Jt4+=ns{u(%*NF&8|c*W{&-B2MrU|`h*q&y_RSGXL5h+ zwS0luW)^*(W8aBF(hk+PFo%={r80f$Zux9j)THDU7S)smop9=z{Jm7ru)1cyno3qg zE__Hrp^-XxNnt{r-gUn-Yy)})xsf+W^0!T6@{8bWm7O(wsUjNL1)-TP8xyjt@`~}T zje9;gK4GZz78-OhbEJTlMNpwpD*1LAKI&L?%JedlnX(B3tr2ez zb({7qVQlTxtUOsvDsnr8Rb)nSN8noh>M6e&$3H8Cw9i8{YDm$?_<>`eBjRQL~0D{ zEdIyF;B z^All~({8-&JjP<9zJKjz_lJm9!~ucQ4R{2y{+EHGVsCHaC}`(mYYbST{3DlTDgDVI zx1jSAef(%bZGAz^oTRGrOfREkk_qL`?rO?qUAouva1I&;r)drY0wWbkb8tCb4TLgubx~s@ zN*GS+fg~G@H_M1sR-=EJ5h3Z(1@io3ayH+sA>`hs@krIaj*uzG*FV1 z`NY<%9FCEINGXN!$!s(dsgsbv|DES>iniAlgkeSu4+$(;g3;2@G{Cuo!!xlqXH`#WbCA~LWiT3$GjcEqJ&*U=j#!Mi6z&f!r~JmziWW_|~7W>fm!f%48 zVv-0GsHk;~(W8h3dw-lhH2YN&=R%eklrR7Ca%RjKo6dT2=GF_ld#MKzX=R%qcaQ9j zd+7BM1L$=YHpKW~N2VT~=K1IN+j*BG`y4aZbF$)D)B|)%(sTNww9iNOH+HMjvt`#W zy1z~0j_w^|i~+Uw_;0?n1U;NhgzSv}DQ}?g4{mAa5!F39JR@E&Nn!}93ODfXOhFx6 zm=vOtnG!O=dzY2@_`aX#?d8<@M5UXejY){U4ykgqWdyBD{nsuREe8)D)_Qbce+suH z1n&_#3P=qTLDeJ@i6Pa!)$-!6;qq{}dwW1U)D~`!=&izr08%N0)=GcrJp+3jtGYofV7nAVk z5nwt+r3U{6HEu zziUbFAGo}41fFe~^J8amGVBgs4x}UNH5v-AJ=IxaQOng z?o_4>&by~1#a@rOYY+W9u;%hghx`CwGH}3!?tgp8_qP`5pQ~6Y3tQuVBosiUb^3*r zd{H}>h6M>3Tb7MC6;zy~cM*~jufY+aR_|-pu7aL4e!N-?br@MVnX$iF@vL~*x*V&B zk08;*C-2fH6sZ&DS>_&Ynv=SJy|36?l|UZtR9@@-r01ZDkyhuw^vV!tEUVjB3Icwk zuyH0b6S$5ToGC@DK4vJI`z=-?Fx^a_nUDeNU{7|u!6G~eKXFOCh|*LaITbnYfeAw< zG(o_yE&!Si+MjyoggaqyuKF;tJRq*Tk^h_c>H<%nI|66j?!*GsSi|aRR(fBw+>YAq%PT(ffcS(F{dxBeAQ_ zMrv05kAYx@frL$p=G)qoHyht*B7$42&oa`vx!Tpn9)n9OFPSI;&NSChAhQWStTVP+ zkI7ZPzaT#yf1{OX=2=^?aiRFYUg-Pb_Skey*4kglJ>h2Z$ki|uyWcx060FAkeuiKp zXUGk0v^I-dKeSdaa(L91{qT7(X9ha$GfX?owGHDlXL|H!XsfNh+rIaV#s$U{(dyc)#}&M7`-M}bx(hue zbG<~(irHqPMX9xtEM_F;B-#SPAn^=%!UvkPJ;=DD1NQ|10ys|m7<&( z-YfiisST6QG#`%E#@8)mhb~sv{kJdY%Eb`cC@6Y$uu8ay&1h?M=46-QD9pp|aCrs& zt<0+{=Nn{O^U=v3HZ^W41;^(uvfVLT!Yn2hA-R@}$1RQ8hFlq4p)!_iTebGve##vQ zPU>O@PX27%-lmTa=|qHlD?%eH8F;Y#yfpW=mD zi?!Am_WoP41CM>`#s+|hm;fN6|Mp?=>n4<|fvxke#n3PL_&?T=Rmy#`0Mhm^>c`%U zU$6IvFCmJsWt!pUnq`8e>DEK{0bOU8)kuVizE=}#L!?#aa7onmu1j`X8EI@RGXykOe+%)2~ zGwduq-}WYu5AO7CY{}`dd*1e&th6kfJl?)z>&W_p;Nf8t+kZF$4I#e{ydGqgofXky zyq*+HI_3d}>Lx8}fT@J4f_&_KgjcTwa|Ui|2=6Q*p=O1LM7*oMq?mwy1cw@)z{u(Ayb@)FNS&x_O^MwD1C}%7#y}w>?SX(@R;dN;I1N5CnSCI%H?#q zzRbb(DuYDz{BjCAT%Y3%-iy0nmoBOfetPK1gh}&S;=vkRez|Yy0ND*4uB~ljQ4iPL z{W@s#|55gi-I;FNx^V1N^u)GpS8Ut1oeC?i*tTuEl2nXJDmE*&o%fk@uf5K@>a=~@ z+&|#{GTJ?Q@8jwhw7xgt51vWBz#?B8#v9Q~XYio{#!XqJm}=MrZOSW!!QlhhS0mPm zeiKaU{Ip$>dS|w*nRcu-Qs6d*qY!jf{RJn-h5CZmJm5Z?9bGZzI6UgQgfM!$9GZwP zQo?CayWgmg`XWX7g+&{1^!m~)nxi2M9C+OVGdMah6P&TOebf=380?+c39>>17Hqo=b(ScCy(A(5nXX**c|2x}XZiG~-6XqPG=KU6XC_rQy!_peJND$frE&zbg*sJO zuc>ts$-_-P2Ms6lt6kd4XoIQAU<$)j)2g^RU8vw^bd-)@O5allIVYr;SIFMp!Syef(f^)(tAQbGBofHJxwTYZ z488|md1r~%rI}Wr*3d^0sw)B5Ss`85Tos*r;95i^S zikI6f3G}q|FHh!MI?101Ap8jj#GlP%9jiv;;Rh28I~1PLwSLH6VW|J!c169hbIBm# z)0FHcakzi5EBd-;jG9FxN{eX)Qy|g!)n#RrJo`6OEP7i}>!d6#qm$rYEQTQ9YT^`S%tDUJjFQh3KlrlT!V=}69#xYg_J*p$ z*MHT?gk0Gqj9y-C3{DMgg(MISHbVz zRUe>?>aEK0uBqOI0pe;O+(Jnbp~P9>E}FF!87k8g&2 zj>K%(=+WS=|Y`_myJd*p4SG(VbqNCwTPxCNtxi4p9C-_reK`?1gNTtr^&4BG7iJ8y__@# zo?dYSpz}RC%&+%0A+VQz-1!%KVeY-)2+S=@e1GrZ^NJV_C-lhq3V4LtR46y={SdOr z2lMD?UFLX!{?CgIUH%B9W`ck`{V!IVDsINEz#gh#{$J=E(Ej>g`pIxrAyJOhim*Us z#l#Bk;G%NxvI-jQ)B0ue?vt8DG7O+x$0W+`oAfwn-}&kn-iz*RU2z2#u{s9y8Pq~b z*YHGa0i6f34uf8q@?oL8hBY3f-aTnJdO4aR<^`GBDwM|igGZ|KF>$ldArl`wkLq|M zqvTzuEpV^?x5UwM<~{j>G7LSpc}&RCPfKwMGIT0Fmwsh zfR4a-X@lBg>yVOFP_?gYc?}3AB!7H&1x|9lC_NCB4;OcZ*vDdKc0{lQD?N)xs=kaDulXns^%#*vk@rL?W6Zc zw7d=|*3JIy`s$T`c6ahTn1%LeAl@ddW+LG+mUaZtcGY@d9awqy_AjLXaY;dMK~!Fo)K)nYcAE1ZAp;P0~o_1RlweFAwD&i(=Es`7L_ z{L}6cYQU)u_Rm@Iv(=5=0yiG#fz+od8+ zctoOJWaN$^j(JRCPKRFEXX?&m+RvLt%$XgltZAe<#Q%prMEHn%z(~UyT;(-g8gL+) z8d~3PkY#Sf%8u=ni5ut_2{-^>w4^={bIYt#%c1(hMTiI2Eh2+&ps$Ot1-2hofKIpq zQ&(S?*B~inH1n8C5+wfvCkYfZL_A$3%X@)9;WH$b>@ii1QTZ%V$>(y>g7-m~`!Ym> zvDQl#8P$6j8y}iv@f+UJ{1!Mj^v_tNr(((^kfVIUp4Oji;zAoOsAjP8k?JPzsOdD4 zYeX-rY+wD@hgOD$%4Q7en4P0N3?W>HhG%y&`tGSJQ0@0DIl= z+kKMPt9%pAE=a{`l(nz;v}V0jQaG%qLMpnOWfn6}lf$Q)OPl5+)^Hy}{hOHl?Tyw& z(%i(wIc&?(QZV*ws4LxzwP|&EkuF11jtBN*L-0bAd**@TIsLmYAyERd zAg$J&Na(XH* zJ4l*atG>7Q6<>Lc-PJx(Qnr+dfi)hVg=4c*Z=pRlfo^k{`*>|$^vuXufI=gAY}byj z!n)?J(_tF)-z{c3w%6z;6p*2f>obUX>pO(}Fo*H6^4x}3RM^b*{~{PYr19>=IY_G{ zA%e+=_o7Jyx*+sEa6lx~QXotBy4N7bh%YlMV_s#>XnRn)fh=*h%NO3IwxY#hdwQTL z<*<|@sRRf&-frCOck=FnRB^k05}V=4*LmY&KCAfnAmCo6rlcs&z($JYUI(*P-RN;5 zcw#TN$&W!^S1(TsMD(g`8)h|dzje|Tl0t)kFdz&hTy1m+jxYU9S7hIpVPbK+eS<6LQXj770lQlk^ZwIB5ZJm7XeF#BCurq zk7}nsK$$=Ht(xIQ03L;4;JjNKB`+T~TxfB&fxWC+#$WPtH9K|0JW?+DC+>z}bbn;$b(nk3 zrC-{n;r&dKw0#bzK1^mIrMdab3))hcN?G*HuS3-OQJksgEW9* z=TL!-0=YJ064a~qY&xj|bciM~%+STAmoa1;HI0g8pXF%Y5-CQ1fK3tE*DC69M9-$= zUjQCCLm_u&FLSyocyf60Eh18Tqp`VwkrDpDkHL7sv6AZP9YqZ|58Sp~nZzNKmLI}n z?onsfNm1FtyGc{w5C`=9O;*wI$&s?K$%P&xK{FgBn5#}wR4~KbH3|%IDuuV{vP$#h z%CfI+Om&{l6JIG`Q@_iInMI)Puimr}``-tYm@r>r=+8^JKOPfF-_z@sT9L?XujzvX zB`Z;PF0z{l)b8o>?eWl3%9gRY`etk}~oy4Ywox*>_)yDE1F||t2gIvbu`~e?%CRIfG7`0bDtlr{Tq}E#vRpuUkDN4#`xzsIrI)4%Z8}fXRn=uS zV`M$GT;4`V;ZH_prRAu;!9VZ}3*s!SD3ppIp0r@CKxk&E`VE zeee~@JJj~YUPgDTtyz>F+45QD%Gi&o4qP&Anyd`LY->N1nQFbdJFOpxg80OYn1FFk z($g7Fod~tKQ_Ldvk1Stir{a1!Zz?CuS;B+X-Ar;T*>QyT@ApfI4oEf;`a+q0pQ}kb>R1gp9!F>V+g& z6ofSk8eyCUZ+wNfp)oj0?5C1i9O_(~%Z;!+l zcd0@XX^8fOub6FzPG|`U44Z@xkp3ox*HTv@Qb-0SNsNra6W2n?v8V~7T0RF=MCAAc zPn<%Hz$A)7)JVL-@U!Z(y``I=r16!rIX_13(Wn~o*{6lA4;mNAF9EbUYRql= z;;9+X?TTrRLF58nrHCcLn#&r;Ji%AiArV-9w>r%`AbaevZb;Ik_*65r+Az`}<7cX%=1UQ%tHpK1 zC%UFg7zgqxYBy;#6~bD0jqU-7?LBUxLA`i>gI3jg)rY1-fJ%ga5k;B7Qt(xkK+AUx zbdyE^)0SqO?x|>W-OfT0-qS)c+^m&6^K{&mnJ~sHTZlM*-4{BK_{er2@#E4D_fBX0 zeQ|kt#qs%eFqbj(-F4&rmg`zjfpDcVcc^f5dB>FJmg1-Xmz(+rCuaOly;{~*Oij0j6xr^2LxGs=Rc>$wx(0S&X`E*$3p!SFEK}r+p822d- zzsAOfax~A=&?DW-CrZPzD0O;ff8Q>}51{?Vs7q`IYe%=&*%sh&4rA+b>Uu$zrrg1i zD>n*xtDHbI%}`$8F-S0xt|7V<#v27BC>|wZ&%12cA05>_UeZER+y~`Mw>HZoRzaZed_Dd~H>`xV8sOaXURzlax}fy-lDneQs&VJBxxnDS!kx9S zAAg;AGaG+W15%#Jz)=W~R?H3mS?$zL$*N>8VN=+QQ&%{!4&4 zllv~8;vt)1d(h?)s_0{0U2FQ74$61Cxj1RFR1AI>OF1hY}|5S8~9?$FH zSW=mql0)63?8T6Sid$XOTwvNn3W#0;(bu5r0#!^qBOVlNS|Pys2kEl>m^W(R3V5W#rV}v!6dUh|4q4R=e~3>dc(E zEcPeT^WiWA8xR9kGnuBC{6v#!S_ZpSV~rken@x@RurBS0lLG{oVnPCcXU6?*XPac%gCE^<)p) zUW?^Y=MAP$OrhVB< zLFNE_8at#>K#oP=L2TWKTe;$g=XLg*Lz2f^4m*-p z#x_9rOcU-ngwe2QIC@@fT3B7KT{$9O-mVz+{T_Y?X>Rn+Q^~K?rqSTFkp!-!(yfiH z*1-4GyukSJgAd96Mi;U~h9I8e!t^Yf)2l3=T!{hC-MGv>3XLAs^Y%1xY%uEq0*FQI zV)t)dp;1<;f^Dy(7GOvUWKy=jo>z`Sdc=$eII$NO{1xu-ckGU12+NiW=6nv#he_vO zTd*hRhnl&ZWc1svn|=|8EcnyGm6^z**V#tcVL#S8eKV$Z?<(4U)20 z;NKTe7TMu!p@--=B~BI|;l~Hlh=4E=;>*fJa21`Ow@Gqw3SU!QU3-dJiDUj+2g zIk0$6w#zsukeL{cbGtDsq{pOi3HueoKKyG6*+>?b1EW)-By|QJ#XIG!C|EPAf$!7X2#hbMGuJQM z0d4LHlzB5gO+x{x3NjmI^T~vfdu&+!t1)Y>On8XhLlr7xX;wcpM7q~K$;DUNaV9!i z^ZKfMSz-0N3WFaEQfAK9joH%hZ5p1O+ava8&a9ujZ^ylar9} zpUD^06nQfQXXm}ygmvR+=ks1jnd`yZ`0{&)t-IRFv=zd~;QO&I=r8VXSp0>+2|BRA0@ zyrcp(dniL~3K6IAc8bEi4$Je3{!9DNKnn5h?I9(Ta`FSxCvWuk#HphsJD<)CY8r=G zmRekOA0TwGZr&W9P~2ae!J$xcE}A3eZ6B9Fre-XSwiw?-xYCmw!QtnE@4S{ykaJva zZD-MOINqYG{zdXqt-yZQ<-7SP7G{vWE5}R zHlxK}A{9hhBKhD}GqWMR9RvH+B2HgZKMgf633XHr%7D=@Xr-G+ zkI0Kri!v%3_EfV4N(21jMMiNoJnR~r24wNUFA1KKnVrkQZx{o#epf%e2?Reh$sdqB zQfEl`HZUCu86~@Ps|ga#oIl#0lV5#0R`tZ?GIs=8kYQ}$a{72(%HU-}LW|uHoa+aWX(0DJYxVbU>ApKVoNl#+{SpgbpM8U}Wc~9rh+*yNH=8ENvEw*w z&5}%1I^IL!aMy+V2-ymjx}cBvz!%)8xqBzT8#ug1E7TEu*?*zYBHo5E3*Vy^j=je0 zW6fS;SZ;?%22@LV>h5DZ+X){lNBSmq9WDya5n{eM!h@j?d(036wjIywQm|0%5|t~^ zWgmNzNFO$us%VGIS+Cpn|Vht6~4=6tEt)6brj#&BGFv&?( zzedxHYAZMcI@f}g`Dsq1QhHGGs{Nq(Ay@9Z^XYudT7?eN@84SnIDdJD%FG|BxrXJ0 z6+fm<=Jg}K7*A&Nlr_2KsS#@C8;yRAo*ngpb#P`Hbm0W2QN;tjp!zAr)n1|`v8!gY z=zXhQ-z$6;v=Cxz_j8M|+?ho`qw>SCrEhkY)-os@cV16N0aKo*-gU+>QUP*%E0gL7 zN;|1Z#N3g^ey5c1#`WIO1D*V3ndNY@)srum@s|^i&P48PZY)AYCT2{asIzurA(su< z(s@Dee*$1+yDZg)z`qp~$O!(YW)boZ|1SB8z-UQ3GoW9@f7Skf%R285Ap%}OVU^MC zzV1)6$>{;aW(Fd(b*iY9|E20=_#Jj#hxmh8?vsVNfvpm~lhD>Hi3WQ)`BVFF=)x4^ z&D*g<*gng+>nso9Hc|}}rzIx0_6dpjneDq@YZqU{%c1IGT(m0w@H!UiQkBCI*X6>( z-knqrbcC$OuZ>Uc7g6eOPL~L8fh3gXUVb@!+!NOLUq6s(l%afu``*ER;E)=w;>dv( z1dYr@*As_1)DUk)BV!e0sm+N`^&E*2?Ifh}>m_C!wo@R{OXrh3`8YD6&b9o4D=Z6l zP1+Tm%7b%7K<;oZqyW2(?WV?;LrMlOiLc!XPRsmp-9m|g8XnYa>YIm03#GYex?QhW zL$duEynV88^0siC2r_DHRTh{qZyA#vj@f`=Y=?;(A@V@pD7^WJKI=x?PrrFlP?V6< zsbM0tw9UogQWu2sL5u=~zcd}3*hIX`pb7zwEk>cx<^dgM+Lc&Xs&1NgA%~U5x!+nq zq}IB;<+R$S+L{~1>s_<;084ne4X&1U*)aFGk0gQcTv-xP4B2s&dFRRUm#C=?gWf97 zsf5wS(A)sVi1!d20XH}OlTfhCPl^^Pe#PvD$Rl;`4$@Z%8>fC9l*7-4K0K2VZ?g&L zo!mKHX@{@dFYBlGH%2i;kx8%b4X(mjwN=GuZ1VwWi{o)auzZ{a|2 z-{OqjZvf+s@?Yk0-WrFN5o9E53_|yYe z=bv5c|3*-k*f@Sl{qhHPi}^+B3k?v!Aprt7|DzG;A47|zk<0(^??$VyI^%L80Dbzu z7oIt(U(^pLX977+i9h6$j$AYN6ahtMqVc#1Hfkm(o8WQYv&TD@dA+5yCmRJqS-y7Om z)zc7J*(sf~BgTnx;iZrlasl$)-yUGW`?@7-(Y@=mM<=be!yVxf0BJLWVo;b&)Jf3K zXiOsIA(6_{)SszDL6lOo^TP~@<2-z|l-XISRFr)_5lZpG=>@{s8ifP~lgLsbOU`)5 zElARV|CV$h`bPe&4bSCZT{DeBLCKoeNhYR454YekVjHbDJZ!k!pJ5`kU>KpSO5p7d zw{2cqlr8ouNKM3qPEbf(pnxSi!31uGff%yjICc1e%wr%BjSam4`{5ySm5;Ip23;Kv z#%cDN)!DEu!%XbX1})Y zz$VC|_WD|;#C8%Bs1G~&w~-leF-Itulkd`6++j)7NbUrB#v--UuPCo0zAWE!o8cfQ z08T{Z)5R$_*OK{1%Wh>V+~^e(yb);qbk!SGRkZNr-t$Vso}n(loUSKj<};U_hTTId zk*m_i=A%ccP8zia_++I3=>Nn?64pD@&U(#5DGGlktOLvzkmie2IjDQXMT8F zo(>m&>HLEO4>xp`?d=a^HEY}c)L(^9{d8HPptP==L}Qlk@RQY zj`OK~q;#Vf5+Vyp9E56WmO;{{Uv~H%_U^_^=m&+@dg=6>UErf?r0OrYxM>h8#SvJ& zms8xj_hfXY^zg{n<|RDWdbzyB5{M+b>g;74sFI@x<)ZZS7|nuP8o&BZD07 z91kH#FO!IBhEkLG=>&7mmQR=<%^ek6tD{$Vrqxh&vfZtF$hK=FVukGkyFfVqhZ^hI zmcZ8{4z6PHnyxf!YuNYzMkQ34Q7BX#2W;@L(##au-7RQuQ}H1oWb~V+8`q}Y1QHIm zdC#Cji30o`_7D#Gu*pjVYqgc3`90&)t2z?Bm8k^{Y^ql!-$Vy=0kGpnKL6D z@GU*e-naMZLMMTrw|A^%S>Zn$sNrk-=wFf=t^Wl<@!us#$l1c}-?H&+RXK;hxfL2w zTtcF9KSRXxf-B-PVkzVq)sS?&5p)(h&(C=v#9kk!&R2$zB`fvgmcQKWpG+pv>D5C9 z{)*(%Gwu-1wo%{GK2qy?0g45fV@ULqq;(z#b2RDFbbrW7o2CDj9!jODhD*X|yvl5A z{|qg|LEeMdB_YH0{4BAQjmo#)g(#nxpIYt+#$08%RG>lFhpQ3P$g}XvILL zI^MS{gt;QEhcK?L%kb(wi-MNew@mT-iBcLSS4#;F&r7i;SkdMnp#mWjO3^0ov}DOn zR~~Q5O=C$ZzqEp?3`CH$_U5C0tZrkhBx&h{5 zfjL;oDw^+UEAbX-a2+$c`NUQn(YMx*U(0!qUO7HJ-FU(eXFK=%#O?lFlJ*y^IYm`| zzpPK4oU~Q58v#ZPa$KXv@PO|3gdT~0L6D0}f>#+OtTiKT1303p<2<|cTmHjhVJ+4m?2i}Tk zH4@H`ike-R>qO(@Q`S_rYFjfEn>mcz#&{FSFw`7RK-g5C!^EsO-vdV$sqqs+u=dp2 z`O=mZ*4l>%SRyjWt<;N>J!&~)T4w%`1$N8pHUtCF$yy*f`Hw9Cfovn7htq$10RBB# zR;%l{tneWF9cY}oggR}`%F9zZmFDaY%`w|;ViAvPM#uTM!scVYdut^0O^-Km8&RNr z*7n^5@&PMIZ*!`!sJf*s#}D~uqbY1!l%55!d)^MddGh0QceG*kL9V$)U5B!Qx0n$D z$Wv&;djYoE@;XG9uJmnPVYmy(l&2DW=SYY6$kfS*_n$lDi6jH#2=3%O)SC6BCfUlM z(p+u8@je!^f2Bxfo?am!Pd?wUJBIU2Gi1pUB~GK*ak~W`I<0B5l0;M1)7LAiUd&#* zxTh9m;81+|RH7z7S10Q5t=?N~F|nhWv$bMx8KT3uHxHea+j2$p(U9;;3n>9SIiuxdE+mTB)d0-FZVNXemLSh4UG zvK-hgy_9{`+zfJ~gPIV2zQ=RDYmG9OkT4&m$Xk zO-O zRdR~ORSe7fS9C)4PdRe4r?X!_eu;8O*D@zUr|wKGdDH4n{vI>flWbUICA;m~&@TOr z)T4fLeUGpNh^}& z@K1amaZ31T3wGgT_bb>vTLHu2ln?GWUk%ycoTmN3Od;!omzS-MgvSjNy8PT};X_9i zqqR!Im{>R)mST(ysV>VBO(CKKiMojd`eo#Y4+pP}P)^CNBFsyi*r~4`g&^iW?xPwfq=wa*Cts&*uh@vDX>gr1-zt~Nfi`EP4& zie5Uu4TEHYCW!G52To?}Z}I=L?Tu-4z1suZ9tQB;_)m?R{*G0XvUfLfwgR&A|GwD3 zo)`PK^|waUoQRQFwAaQwhZ-hXk$toFVSYu0wIkF{!czI!XOx{@kJHcnelTPpsqU&jAvi%k{bt%JXX#e&Xi~ze+&RZBN)DVx1J-d3g zUCWODE0Munz+P1mCex0VhmdQATgwgQBA#zR&$brPn<*q=^`?)tN#>ev;_{d#fHqB? zY+g7XJhu=ULI87Fr-vmHlxp$<)-+%$V5V*~dEzPAc{%`WlVc)m6)TuEu=0SIaDrq` zaYINv%7{9$4a^(?hgL|77s=%qtj!dpY=lEi$wLUfxE?tQ+t8t66{Jz7cogQB)7Q*H zcI}Xr3x$_)gqvO5krnNQiX|{dYBwv1xQ-$dxOzHg z`bR&Dyf0q7LDAN!NM`Cyg=)VYwoIwOGH|lr?B%nap!{aS#iwCIEi;)d<%eD|ms_Yf z9bq=bb5CigGc!rrSgPI%7cle39E|$Bp3tf9PiXXkPEQ7xrhHha=!MQ=;AW7d8p)2q zE(RVUUUE>Vg*6@x^43Q*=9F^;dSL;rSzr$EM04|6Jl->WRplCf8X!B1$|$O)_4@fr zOwj9>E_W{RMrJoLy_$`sG10>xb^ls@XQ@2zG8LrCT&I^u<~auKE(M1C1|ds&YT7B= z$NJuO0(Oq%?Q;j;+@P$Dg4qdA-jnj}D!LG-8Vvy!$FG#riCxFxW8XiGM&JBM#?i zuRwqf3iuoI{X?Km%HGlps9HBO{evqQ9oK6g#DpB?AvhRKt(*-#0;bH$lq4F@>srCE z4}xi;VuB;4w%Hw40GI=H<2`y<&%N-PqhEj!m{aB~(t%U^9>XBeD^Wo|7QbEcw|(-eP6m_PnH4^tl4(q(zp;cvbWhCyoQPb!T#FP5 zQ2+u@#3L6PGHw*pZIPUrC5Q^Bu+)li+i!SR%U4SoE;Ot~MW!kSA$IdNN?CastTx9n zi~gpsgP1B%qa*4?H!q^kl}%5ilnRU?W4RAVB;Dz@7@J92N_eUz*CJOX`mqRiyXl=o z?0g)mWw6&T`O8&Tcl3UL2zJEHc!C~)r+EfcDE`w`0UxVt)xl1D|dc32RL(0I9?`7W4U)Kfmj_ZgWd*Um|=i>#vPLF1v z~zZljrb}^>&RD(a|4ObTV@%3!9v z=92T)Bk;*JQ#tL>%jAj1D@wU6=OL5SB^EkmA$#c-zRAoGh-dh z1Q6YPiwNkkE$$$kR)&Lr3lt_ywdt~+CcCF_AKm0s!jw5$H8Vd?=T0>XK*h8Gw>m+A z5*N{@jcaC5oMx!}glKZLRuG&+oiEwS1t&OmHhLoM?wxR7yl(XRV>&#joN}UvbBLrbHE6Pe@-)8md zo`LU-7v~eF`3vE#z=@n)myO54e5h^2wh%03%o%OPJ+gq91!St@ zLCfLf@!ZHiM$V!>4ABzcS!DvpPN9EztK}X31mJ-xmVf(*s;tVdF(Lc@1h%MDGqnk5 zTQQY-)t&sLf=fj;m`R?*A9}+aJs`Be%%BPL#IocTWm8_(VG9O}Q$_oF^12@M2GVx& zP0!P#<>%@&`B>Py3M$o$s@O~1Tt!Q^>dz*&Kgz0542E`(sqF2{jz>i+Vs{zX%`}@` zT=6_*;+;OCdHe0F)SW%>bn_jkod+$(%|K-|6Xy;$eVO_|vS%Z#zhRIZz}`W?FJs|J z&7TsvV|~eg(tB?p-yBCV*C2M~IKsh#19AzZ%!#%(0aRb@#8E*tC`9|8NhRuS?Z$pZxKgi5+RS?$**%cPr>N7~5Za zmZI5CK&$m)^4T!p!W&*C8~ryMt{C@m^P>#6ledSSo^K}~^;oxToxfMvb^ zfAJ_+Hgj^b0-8wvXANprUHwZn2y{P+nhQf!O+f-tlK84x;cUgEpr&TGfaZKSYv0B($lJER|Br@Je2sQX#!G8>$=y9Rtywhf4=5xg>mQ_ZR!l zU5N*s1-Z54*U7+!#UEAgRwoK>|wUI6H zQsFMsC9B98Pu88^gTM2?Ky8&0Tc9E$$Bu_9rm*#E)j=}CUF@GxfCUAg5}(N8YVIlT zfzDeT1tm4R#hs8q3b+6Y4!$^qLx`;>nb*-$g&d)(*H0fYO=NtV{o05Qm+Nr+WJ9Ya zKCfdjV(EMWpU@(Kq{;g|10}39T&MZ{P)yrdjLGwW(v6Mk;oIy_Qz18u^VG2`i_Pkv z!MH6Uma&CxixvP6ZLTF{$V|R9GL6O5LMnSQ$2y$DWIY3lTzf`=@0aUOXOq4xU$_+P zDNo`{H_B4la6x_60i!*VCuvk|&4pzZr2rITDe81=Oc=(?x(JX!umB#B@`WLpFq}@k zovBeEJA`Z0JVL)erNKO)W;;rb=*?m(<;;KL)9WqBc~Di4FQE?~)=c2JrDAPYT@qQZ zJN~TR?~D6GXRe1t-Zx3=I7?;tH!HrA_0~q5f&R;iYZ?AF90AeMgC*0>2>9}SM#wsX z=QMe(0aW?QM&3eJYtQf@;ZQh4y$JFmoRQ|t`Th~d{30_)^f5FjPF{kJo{{*4T#61O z8!!k7_+pOj@6^-B(Xg!&6A2i3(*^BSdaPmaQVI^5Qo?WR%3w|7=Dy~=XIYygb>{0o zT9W5leHAm!=v{Z2Re$C3YwtNd`pXaA4%JbA`GlL-)d@g;)vj=}l}+%@AEbwO0DjigAgh5}O_mGOspixh_1mxpCG ztx#{)QC*^2>>iib)z9MbR;hgDq{T)@TMber{Fmkp-(WRDmcH+EtGU zg`tR;%~0(SE|yBe?$go!R=p`Ub1=!OaBj3>h~j}-yd+IV{gzu`8yC0?9G8h_OBZcM z#^?@a(Q>DzPF4yE>i$tiBoA#OZgz+hZD3R#^p1$aICV%jq2286pTNGACGW8_>BRTt zQ1=avtuNDPd7v*aPw0}SWZ`EIt#A|~HaznMyr=*K8DMSG>#)D86~|%Ic00*!I2w7? zZ?`;RRfbaYb`0!;bRZpV9WS<->dktbf1NxpgG@OcfE+tPw*`^7xvr;z)*(@ zSxRm6@x;9%q4*D9GBaNL45;NgfufcPLc-D5BAQ~td4#?vt&)Q>!Wm4URQC6)NsI4u zr~17!6I0~a6O4a(@mLj&MLLZPrW#w#gaDTwV_j650YOq{^N8`RTSypWuOS(?7mxC3 zVxxF161+lku2GRBL+Ah~!Zs8J*8Gz?n5vpq5Vt6_Q%qc8%UG#G4G3hsBY5cm0Lm9C z5hh=F(jkCN70{fnWjy-HD`jA9o+Av}76G%O1qJS4GoEN%fBrt>16)_jrMfDFCr*i_ zJWp8wM-L67PCl}4hCnM|DbcKn6fB;Q_{DN83rUL-jSmwxj!$E8mf$$4_`6m=`7=A6 z>YU4`(5&jgv9)0R+fAtHnh8X~uqtMrPv5?aKH^*+P*j}1ia6i3%iU!XQv8m+t?bIF zmD)FE+F)^FI$v_?7)U%FU+g^E+dW%0%#w6kAvJe*@$eArPM1Hwc+Yyj4-c+*4rns8 z9jRhWIyZd%Oe}~560G_b8Uu|9=*LU}!=&c}QbR(sxN zHsIqOnl8Ee>b9!#;3m||SONK`iOrY<^CjAh37U2wM7djk{@5E+849%p#R_{F-zMS8 z$MKffciR|}=t&bUft3gKkUDNSAsseDoUKHX&vOnXlJ2>~E5BiOV^46EH$dD({nw_G zw9>gQezZjK%p-sfc=U=oSO$)sESvuzXH*#`N0L8T@umxpO==xdR7UlXmas+}`zb?J zE!j&lxBWma<-SXsYy=UUj1(QFD9C0(z@8xMpHPgK#v&@_$OU`N&MnU%`UN}+;F_jUbfd`p5VP3 z0iXI+iptdpRAhmfc&qj#TR&2>F5h38qgk7FQ{{AX1w>HrM;K$*_Y~yDHY(;;WX>1T zw%zEWUaiI%abCCVJtvvTkVxz6UxTE}3w`l*&#Y=BCF)L!SyFDi(-X{uY1|X7Tja5( zX2}!a?C_uVo)&nv1m(!Krb^QR4Lt`2tNIQT)c^x5jO2RLNER_p^jMi)>*Ek@p3Dmm zF9=BjEZI`VF=P5P(_+|)gU9DXTGSW(IHi|2k2B~`OW))# zMFcs(ac}}i$zlA51xwA|&E;Q7Mj^n(%qkNC&~*iQot#?vpa)LI-uBw<&J}u z8Q#p5KshQEMDpQVw8t&QX^JUQLhwW&_ya1Ey#^*quUJfMFyr*sPN@4(&Ft=xM&uot z)LaSk!hph>v38+;@n3nN$umd8?_BNQIyuEUiOU=h*&9>0K485hchWWBL z)7+=_aj&3%nez1U&Hm25rlM3x4&5XClQ6Kjpd%RZJRsXp=&P8}loG5pHb@GbvQ9%D zUYeydB6e;0=^*`fHE8!RBu4Gv%<$Ro%0uayi>xX$EbAO*e;Reu#$59NYU7(Fq(g6Ut$Pfo9=rUD5KEwpRCI@kQRn*Y3z@l8-c z+UI9OAZL6>lh5NuL``A8rJR_%zf%eON$@)tLn@+mj*#bKXvbQxIQKWT2s@WkZuy4Y zW66ehZln#q)7zsbnfJ>t0Q?vrs-j^^|7C8(m!+|bVB&j-v}OQfv%}WMc^7N$Qq6fAz+3Ro4o0fN6>kg z^2s(XYt4<9p-=--&XRtA;E_uFHPfep_wxLhwY#fhc>PTV%r3>K zp?lL%!K+~!HqgcP?lW$nTw`BTGS zN!}v-#i$d0?0e&>yiB~UKBIn~R)PunZek*c{1%=wTNUxIg3!s)BKn>OgqQxq-PADPxljjYMmz4^y<-wrlg{f>=pv?3uL%{Axc@+ zTJU9n(IMu3NRbLMwr!zkDa2x?43c^u9Q|yAFuj@YQ0@{UuF*%R?-BtqvyhHk(#`(y-a5F=HP2E`K&5pys z(T5V7{?4jv0b6nhuOpdkE0OZUM@*_wT%QVhcp;S*nW3P&NxMFr8{0Z^kb=sr06}N^ zt#FtI7yI)}mhYwxFaAm6JYF-|{NvH2rroE1Z)#Tq)d2fj7o|EO`Lo-MQs5c}%! zxcWfB5VTEJ7P$GJ3x{2BW>_KM&NUc;=Q#0#_SYvmZa^Gt4e!9S4g=MaTuhu5``eXOWyywaMG>bge zHiT%NMtUKQuRt1obxXctxa{en*sx&J`bv%gsCigU5eqb{{AQN^m*zoi_igiCt5YW( zfIES}@N-oTLc8&idiW+3$#UeJL>m-TI2q|nAnZsn$IHR@77J$2V5Qm(Gpe&zp5b8DzK?!#TP3Sb zsgg@RR6g%usS^1AkF#%Z&pTbWZe!a<)7WTi+qP}nHXGZv-Ka4d+i7ek-#asV_Sw^O z=Ipb-KOny=?{z=-y1iD=lL-Z^3|pC*x;$pN((%O{!P9UfIk9@faR5KeDQyq$#TL`6 z%_7$(7)uaKjj_g!_h~U-X%=KeD8G)j{nudkHP~a3-;txlv7s9q)3PjtLSJ+`^FVM;DWxbpRlcn6k?-ZjHBj5V z;IJI;dvW%`dQ)n&u6wDu1HXdz}lopBv2oV4W%j#1%d zjT&T(DwM4w5tnv@C}j%4of2Hxi0X`aguB zH|KQ)oYVIPGz~xB_0At zVZMB4Y2{7fDv*b0t>@4LP5uf&)LZtzyf=lWgj#8xg&vb5Xw9NXB~rx^l*f_fC76cv z%;3`vFS%u_3vByph>NXQurB8|YwCsvHkYB6*~#Gwk4KdEso@Oo`3g{6vax38wTr#X zo+JmmT$~v@zmt1Ecp^{Yi64BT6`dLJqm>@Y5m)nfDt0w=y&K;xUbE>IU~PKxwjwOd zK?J##EY%KKmkHl6d;#$F4_#B{DvT+0QRA|;$_}?C|fDVjC$9Wncf0nmuJ#5 zZkoNh9InZ0atUbEd?F9;iggOK21-iy19c~9T_BEGc3Ys%&9TmBNaJq>F07*qXNaJY zc;;oDZJ51~=C|f}aIThz?5wr+ARM|m)8d#jp{A2HZ#&$&_TubJchtyFVR!QM z;fWZ!baZ|fc{%pv&r~bqGIzhcYN&DaZO7vOfgDwq3FWK_!I9A)5ScmFKYV&GopIJ; zEnLOjvYpX7dy@O=2bE0ei_Osi#v_Z5#5E@%bs+%Ze4}A>Z1Y#70)W#$^>1A(3~dn02@BZJ?FEB@EdQ2pOOV+UYj{%_xMG0#Zk26T?>0a?Z0-pT&s z=lsjR^!v9&j2s0l^&I}80~N<-(?(Tp~9w6nJ^Oj)!OTTuBp!Q-F>opGZV5M~a&Ea$(UQN+DTTA)=IjtAN%At7<=R zxQ=1IH~O4SNz)|J!U~6n2%0zzsj=VCJ3)iur1n8}%ZiTwfKBHW`I$*Pyx)p-pGDw+ zCsnE#r0BvEkI$Sc@z6eDF2~Ssia`%4aNPMoD#!a&>9S4RBY_>tE_#NansHpq0MYRE zqNP!$bH8S&Et$L&nzgF)t1#&r9n@z;s6>y3PUwV-K$wMqQOp+2dBTRonX2pUPHyb0 zCp=)v*1M0rYhM>T2bN3rAJiPr`WA1+8T$sOAULowHPyuPtDRnI)q?{wU!a#G5RS|- zyKT_4M9Yki?R003mlB}^n|ql|Ij(*=`(tA?CO!ceWepG!|91EFZ;Ya3ZDDQWVl8Fl zXlnBZtz?qI%5MVPzmGW3!+V}TYAEF*l*Z|b)r--}41a~Rvpbn{256<7AAdravPMrz zF|^ENV|3VWDXVI z;{TmFSDr!wdswixjMvQW))g5YqC#(^>)T2XMrD8NA&*`hQpTxG0CL%aDaRO3akt>@ zoS{EvW#H?+ewN)_?#s_E#d=R4bQ!Yd)r-QO=%cEe19P)X!|Ri(3g`7w{qcwWE=?60 zW>;zFW1qu&u0w&yLg5|3FT7iu&@^9E%(FEGj7=RH{qI~HQ8z-OwJelX#wfI|b#P;R zeU9}9nLo5^VuEOmiE)~Z2HnK@}!`jtgJ(j*?>_)$DXSbz|BPv&t`i|~@&4#s`xRF_=p@~ORWS83#m`-#K3RbKN zmXtO4*-ze^ar1PRvvc?TlFRjN&&kdE;9;HeJb~3qyie_7`g&#H9!{k?>Qi@~ZX7o_ zu&V=h)b=!$sQ<&_o^#O=t~Q$=2v5ElD_p{W;~Q}(y3YR5tl@|Aycsg~eDkMf_}*&{ zmwPzo-NE$h@8(CwpxGSsj>4Gy6zQkgFfOd_w135_iRyG3JAh+<0+b8?sdNAC*~)sB zzfTyG6!l~PXJ4;bI(8ID6rt?=&vao7D1+=_@N|lO1!ifn3ED^sLjc{au(G%N%*@EX z;KjRvHucH#wN4MI{%aCi#0GLTZM`l*1q|&S@pO_=CoPKs7&IgY(vl9F)(qje5^O7+ z)l2Y+Pbwrk;$}m@y9pC3SV{c@H&UyTc_D>b0XDz~hY%t^c>1auP~7fWSoewq?*rYO zo~-tYjTfx;OBQHB$MMh4MQY&9NT@I@VbtTBdh{|ybCV~TCO5&CnwfojK*R=SY6RrB+b>e3%Rh4XI$G32%!xkJKZ z_qsxC9Q*9O`K!rMoT&$RmGEr%z;LDnuAJb;$r=b!<5Xt2ZhpN7LiGaTj-)ui@<17a z&eSM^og{gZ5j>f-rf-7XXX#2{X>xtwuF|A_tsdFp*gww9<;Kap=?rO#G4QsZih$WV z&zX|{nUq}%Tt4#g$2=yM4Z)XSm)N*Fq|8ao9$g3h*ukI3Pw&p)(O)MlOadvo-wzeI z*VBd54@v*}j{SgsEa(F8uoLi>|CT27Z}1Qhr2Yj9qvEAx0R3m)^H3b@Xf_YmJNOxtIDKk1;Y?!p~r!n(s_+zF4W8VuqE+4 zjhJ>}!ST_UJ>KQi%%rMu6pn?22zOwE7K~PPT0W>^xeTn%ow*eP>ynDv-vZ&=oR+IS zKY+UPIm_R$!c_uAmkym}Xc@&*4emOi9UWW2p0oW}DFs=XFZIQpR+wb`EJKy>r+amJ4 zzXh?*14`j`bTm|rk`VDAp(SgFLp=?UTzMrW${|cqf?9TzD}LcXdUmF2)20PHtERP1ijN-gQ%GQVCWt_sNh^9N+uLfEX3lt^vexz_eUM6@W(t+aGnnVUbN8O9{Jw?p5#*5&!%x2cIrZy%0(S2lBa`{W%y)p|vtvO4ithnB+KXiVn2W|303S%KLvM|JE3i=pE zyKG4|D{n3Yiw2as)8$#ks|orsMZ*f`5tbtdNKuTB{4~dJ)l^wb5$?J?p+!^|R^ncR z6IOD{Eu;Dk8O@@1>5YjMR3Yz}?%i<%&>&)0;IMua-|Y0c^v`FDc$2NnXl^5$&~Icv zNMo)$b<=#;GQJeOvuMYG17`Sigf$}0QA|=wf>;%LU0M3U0-vuzs=XPGgrs)5Fq?8( zRezxkiH%-Y_GBbt3yv#cC7AE^(B1u^$YN-W^4Wf_bw0CRGZ03eMI(bQei7316 z(#hTnyHM_G*{)p*77l;Ac)Hq^JAGni&-0Q|JUKzg*@clvC$El`JMZUZb~PTd0ycDdmdJ{+TSn>hfgtzVn@ilg)W0s!+n0HFSFcgp|9 z{DASJG~izG54?!elIiL_%9xJN(y+Aa7x{kWbjR1xojzPDp{ImLow$^7b7Y7h4NHk*h8%4<^wn~hUE{(!k- zG*h|J%1+B$``9-4Qg-FWDOiET3}}3+v$TY~7?CF8frf!2G*>t9wBzX@dt%}@VRY{r zL4z=@L;10=j{*7u+AuDMrK|HWKTTA2`d##9Gw~q5QxcKZz3Ic|ft#-z0991torAQK zZq=E+(pTF}m*2KcR&mzj2e#9J>0!rCq?Am3YL^b#Ib?!J_i}0S*eW%t7IgIo? z9y}O%WEIcfZQN^W{%P5b<0}k*Y3j-*S)4!Ol_*L3dFl2C<|As-z$JJY);pIE-(qlC zy_Jf{aijZSS%#a-r``3g5x-NdhrFfPJ7(8k#tq8qpWeg(HV+3lU!R|eto@_YFK z>Expt0m>1^Ep9HUeN4CF*958CF!2!sTln=OXQw1uHp+6bo*dXs-P3eH&T_I} zQilk)v?q5H2`j)ka!>t#sqTD|VMm7m*0BJ1L-%X8cWyv}Uu2lMeXdw)jvCQ`~ZrB&KXfswdUcNx2Vod|M z4Xe&*wuyqMsa6(TF~8=K;wZgCN<_x%`(S3+wF_?;yp_FaHkK`+K(CX%N13aMHq-*R zeyxRCyTeK6HI8=W^(GyEJQ&p9IM%t@{ZK4+G5#jk)oz_UzXvDNZ}@&{i_wE1UqQ{z z-UbYZJdg=o?^#sPQ^f?=%i_Lk6jZZU#up2B_*OG*T0KumJ(gU=L<7t9EZe zIEHjsO zfzR7USaCN*)DpXH>N`UM`mqgEZ-`R|5?D3H_BZk!FO9NzByBdcOE|@(OOoHbXaZ{B zS2m~kX!2Vh{`M|lXDg$0f2Ec#+b_f1%UWl}j zi|OF!%YWSvn!@+unaYKCkK zk(35y$xko*$C#=m_7c(ROzI1I5kAq8RGh+ulp)Xb^6X zd;2{({a_ERN&cYBM1M=vZT)DY;GRQZ2+g91fb!^*e$W1LP}Ol#FyE>X_BWO8ex8Z? z@n;G(sslNM_hppJ66x2v`+W;xj(8ZiP?9a&;=$QA4wTXP^hf3?@<3)@^Iz*ez< ze$9Vc=l(Os{*nGD{+DQ54QONZ6rQqrn-W4gFu1DXa*{Fx;X)=;ZggfNuBzf*H)Hh5 zXHSSz5?l?N^^R0G>w$r^YJ>(g`nY`6{1F)1OR;oj)<%l8s4?u zz1D8K@t51axOpASTYP+c5nGu0jvCz>2Gi08P&l+OssJe>=*F|8_2^iwywO{vJ{bY0 zX4%O*Jg=%Gry{gy+s+n05gLmI7#fC6sEceB-O_4Wv<~6n*4xN*!9x;$r0=i$b(sF6 za*vb8R0`#Bl;SXByjEsGUC81ME#)E^Su6xIFWV?c8 z^0iLc#hXUE&z-gH_ZsoQm=igPTJx1Fcr1~rPB=oYZG}AT5*@1n+@%vZ9hYS36V=A( zDMxaNAOdhKohrS?K2@{Nk5cS`F3k%jv-P8n$WGF)QE7kcGZ~edX z$;aX)*!gk&NQcO2WNZi)#&8%O@#TTDKcIN#icV2iErLZydgb9i@iM1xLWRQS5yjTv zd_+5_N_=BtfBf$0*%BoK_c?;!?iz=JEbW|iKVj`mJq*PTT%rKDGDUi~o6cq4c;Kef zu1L0grG0`nfY?3E=9|Y8u9GgrD)rvo<$yb#wSHfUcc`1_W%XM%=!MeSkYj+Je|goF33%!!mluT1k+XevnNd&2Z@F$a%U z1i=Crv#oPoEtW`#jC_G3u+?xLiHCXNJG+8yu@q{bT{X2oYM6c%9Yh~@kD-OJlR1Z2 zdAxY8yee}ozNGT0SoT8h_j|5AJr9d(fW1jpE718TI^a0Q!EK$+Kbc=m0>ADXA#(#a zqq79w-fdbT@-Hv(?JZ#yS8h&D*bXLsfpW>*_6SfO%`4S+SPHUUAdLcAR)ae%e0;+P zH@tqs>a0i(@XdlgPf?j4F~{VpM*l%D98o#s2bFE2KZuy+{R74b_2rk#A3)0g&$-vX zA38ZY*;_jR$k&a`oQ>@N+tBG>zxB84%KwZ@fBn|~IK^_}S;(FMJgQbeD#Z71ila^knpcZXx1ZtQW?k!LQ-bt; z+L3h@BZ4F#yQ5^&qK-oTd zR~#2hM8M`JelnL87Etcq^5lBmw^8_%?1RgbXb78~bH&?mO@Go)BgLG2p?kt*nUTvJ z8~7Q&bd#5*5of0W=(7koZvFRB_J4RR|Mf}~SAI*H0k1?jOfe4PWL>e;k6>mviHKS5 zCvQHtPyp8^wMBJ(JDd>N`?{LWhqyqNq}Zj*(WO+z6r6mv35dijH#z?4j2lG*ap=MW z?SdIaqpZ&whhwJUqMWgJXV8hA$`S>wfC<|cusc$HYKU49m3l9YUqK=Rhx-29iUmfz z5eN5c{!(K+k^0#eyxgoftrgDn<^A2dOAO~!icC_XrwJE&)B+t)+0I8PAtQ)=r>?P? zMcJLPxu>BaYSv&4YN}pyjMA^Vtm1)gAW42w5M^n;Mk=xjyrLtYDU5N|d0Tr5ORZoa zjwh5ZbF_NdT#rA*a6XhVP1#5~h>=pclzCT~O}PXEyF`7$0!|sF4T_}?sK`Lr9N$`z z!S|r4qRu4r7&vOQsX$wTVc^DRhLi0&V#CZxF4N98Mbh`8_HgvsD?U$&yYWK*!QSWR zL0D%G`I$81+8}cV_aP+Kh5{;m{jjH?rbd)3ppZgW4vDJ50JWLzRPhBNkU2!Jf5S~l zvZt>sk)Aja=i^}Q4rWDJxq_NYk0MY;3AnlWr$~X~XMWC{-6rE|bk_}u3tN#h`|}=$ zhHl;`n!V?iE~!9(&}Iq$ARQr?zD**{9?C(x)zA27v+$q>jhp^NjY`6h03%K@j1*70 z36w&@stm+rSQsib10Lf_`zz@s&+gk z9Snuo%MG8mi!iY~{AbqlnCV^p0m^FQ+fay7Ha{|8k6Xv6-~Tax7e?D#1E%tb-H z2X5gt1GHiV3FTH43|C3SkXPoMc>!bSH3SGR9%(ye#w^T9npQH`@Eob{g28#b^>mus z>goQFfR4{tPI+V<80bDF(@EjB(Z;oX>)c>3BS7QOK8c|!(Rp=G@KPeNM6*Fn|6N2k zG}_kjiI{52h=zqHfY@5zk$QjBv{)fCc)YBYxO#S=TQzD*Fru^S6+dNHKSG3|^FXQj zm=8SWpn(&X6~R_zAkL5%a7c59XiBe-9K=c-?8 z)Jo#il80&FB}A72FDl=Vq4U0f*BxtP4WPkW!U_>h*5<7?K0*m&zh}zU!rQXW!<&iN z#Bq-L*IMIWV=&Rbv97b8rIXSB8pZ$JHp?Gh_#b1p^9R|ec)&9g20XLBJ%Rm4GVm{- zQE;?3vo-*_h1>x>zsb0?DzSoYec+D zOs61CQ$uIOeAG=BljStlnf~ohG?gU*MmDgSU{&N$(q->~m6}H5D`vLAT{*1!Z)Tol z>*OWkB_keaMfcri_;Soq;S=*;^zpGi(|7#iEZZPqYglH8HF|#bzPg`mCW{$nNRx}h%ucLB8Q2F-g4*U z1a&8ff*s!{>|m*J_J7%772I`QN^imOwdHEqQdtN-HqdCPQe@bxj;BumG^lUfpNZRB zr6!f^BlVphZtxxNJd)O{laKeT(h85EAC9fs#Wswb#|)hpud>#lNBNf(G5k5doJuzk z)Ye5#PEXl-_4e?66b+9}GT^OEob_fiwTfVfHc2Y~IYA5~=;9MyUw<9suJTLwxQS01 zPYGb;2|(QacUbZlBkMVu8R%JBx(T@&88|uW0j|jZuy_3LSR!=)79Q6|MnH$(^I4vk z0y+mOcg37ez!tF4VwZ!sy+Jd>HTvht zsC^Da)XPbzAHMXd=!5JJJ-GHk>^mimc83MvA;OAmW+LUi0@ej&x@KBa26Ti6Y~4?! zcjk#Gw+5_2>2cROGv|&Nj=FdgpcG0mU80I`DdD`yzOe}_Ur|@hd#$GY<|rpQC}cF6 z2`>UD3W!$b$c^qAfJ}On*&QLik&J4o+A&Aht1F zB{y|G0Vi??`&WSI1ZHwE_=jKqtw{EN_sf4|(tkQ;lDw1*5IsWYy^7>E-zRzR4=K!b zVK}mZ1K$!bzn{n-HCZ%AAZ`1&ppEchrWZI-TifxXd#9I=|!qWo^rnB9ayVjk8ud*XAt+%y5vD}8N~zd9)%w;~ z*i#gAt3f3VcA%|Fs$?m}!I-1raJz7@N2l#AY;!ZHftRONpzq)WTevv;XS*g&?-?y_ zg&bd~iOg|MUM}RN5AH`yadg5C0R%Q@yZ6JpZb;pd)a1cot7q2Kog!Zr|D~JX{*R`x!;&uV%}?w1NQvc$qDr6#92NKmX!seD?NwZjwgU z@_N=Lf4ErY?-O?vfQEF|9CS{_QRyjKWuj?%zxWgpMEPA{q#Go8bmlS~75|GzHZqiD zJAX+EnVs?ec)A^+e{=w`yenBDTQO}IoYL~ccs!6sqH-~K6l-PwuL1{?WEK&cv1#Mug4_z2slm+K~6h2PSR2 zEm$hiqdUAuP2at%(RtzZK_BEX8bb~|~ z{+dBp7G~nYkUts%Pw3{_a*o%N(=5Rjr_8tmtKuCcxd28X6+!)pf40+V5cQiSt`AuJ zD@I>&Y(cW^r04{t@DRbl!Hakm8J{a@LtQkb%L2qYuHS_#XRwJ6Ow1|0*=@j~XS)C4 zob5q%)so>IvlkZ08i9Gl=?Sehx`a<;!XsCZCIq>zHu?Hrj|C&Xb5?K zja^-~mi+;p1|r9&EIA0;SDvAV|ADC)h|J$?q)_m9dGqaNc@8t{*#Nf1NDxfRN##+jpD7-n^0z`dgo?Fo$6=l5e_K=aOM@CcexCQ&6iIBNU+`oNV{0<4$t z;TJ^krB~rR1|Y&K;A#B_k@}A`@SlL7@Fypb>dzpei#OlSz@Ub35JFfn9_eA%kj?nT zIp;+H_p=8nWFV}DY3q{By6gHF=Q+kk9ZKj7`5yMB#+1dly{nwNMC*44lA|mm&?z0z zQ9N9cU5-NP$C0~8W67dKu~MpfpfKct2%LhTgQ0Xz+JJDh6pj|D$Q~kinRhX0rO&Qz z={Ss;{#I;0Rxh4qZAD$H(8S7^p1tX+&{HmjwBbnu$_K~oby%4S0~Skw-9xGr3|5kz zWxOY^kQ=d%k9G3%Wf_X`p|RhHmH|sJvnY&4`b4 ze+ z(*I#x^)J9AXk+9cZR04V=V)LmZ)9TR`bYd%kdgtATXi0&sM;RV_=mZdDUzv!c;q0V zP)ih+mBqTuixs7h6)?i#^S|7?e;x&sCj0!vum)HJEjUB>WX6=<3Q`lX zfd-_$1af8<2nCSykvxOMNZtDflrOl` zCUHXZqnG@-ff0#HbVs0;RJ=W^Jg^!(>DJ}QPIe%-0ARvP7~d(HA(ef*RN&uTOxu-@ zIFt%)8STiK`s8tXj24x2DW5m&#VntMx;^FCmwa z*}=dJE|kdEEy>iVTu3AOVpqC0Mg5dh8^3XwT0!E>MOMy7x$JL6y<^bOk@Bss8LaPe z8FnKdJKCdp_j~<_t;v#M{_AuErEGoq_2bc!V}_LbNDN-qT4vgN%U5k3obl+1qU$3| z^f$NmwhV6Z6XECl5X$ztvw0}OLJJtatQBj*MqT~DNLpFsjN#A;TvE2Nk^&Cb;SV!E zcssBmzR8K&eCOD5zxamivff3~2J(Gxh4$f~`fXi!=k$Tf|Y?98CSGr>Vjn~9{tPZh~nUTcT{ye3UNX*p#_ z={((DoFRV1d;A()jIB*Trd8AM%`t#|p<^&}20OW|O*!7G)imzay7em zAZefn3l)=B!hLlVm*>f-jc32uh4F%GoMC%nxA01^x_gkG2!~Oub;D}gYvth5y`#L{ z>?_uI z2N}Z%bZ{H1ax`umyk(9opSo_(ORYJ6Y<_NE`a$8w*V&%-icw`sRoPpikTt95o|As8 z2i0NLU>+JjU~-C|r^!1sY({4}=fZe~>;4Y7Mv|!e>?xYWlq})#(;@SYx8)>eYrFPkr-iJ|RtSZ5%E_Cz9+D{fX z*^?UfEph9DWwGu4;n=}Q{~|2~lF&8x!;E4Gk(6G851U_LMPHN3Z7g|q%j$yw+2RtM zt0g*uMMLG8?KW30x22@am(S-zwoEOjdk;snn>_OMKT&J*ABzBC{1+f@=1-+;1iW(t zK>zbUsKx$#=fd_jR)BjufTpVRKWZ_>Y3Y^UPD)iY&1gYUiL)>jFbuGeAV5$~VOvL} zc9;R`1!g6(Z(jH8Qfd4{cZx$?T?bhXFR6+Ql#~bEA4pW>QRHa@=ayZMP(OC37SPCfNXqbhTgxX!seD6rHi1g2-~r*FOO%FPfn+aPBwb)#@Zj!envGSni!77G@|Wu8lG0kX_(iG!I;yYC8q z&dqf>GV70;UPnegr2cqZ{9Q-7wEXIU%ZT5wMXAJN0#e%>tf8)#`+3M)3B347L!*So z6*K}WC=$^m9|D0GCt=vy&rzP^qlh*^IQLEI8PSTjdQdrl(KBUi89iJB+59V+RTAA{ zdskyKTFy_R0_pFkH$saWN|9lDNV|N2P4dI_4amu)GLv#Gv#Gh|z!Jb-^(;8)CR=mJ zavBHg4x*Is+Dl^k5-1{YT&7KoW#{BQh2voAzk=K`?z5)aPuJg@ahdk+6%~n&=EYeI zt%E+`F8V3LiLh+U`Q>G)Kz)CB&!c#H+E}#bQEj2gfy;7BlT$@@&5_vqS*;qG z(aOXlM9f2A8($R@Lwo2n)I~X?mjup{o*h!kmqgtG36Wwyi*WyhpFDb$3#!-lSeiN2 zWYJ%Ju(Hc`)i-We$lARr2j2HQt90Qcg2RxhcvOi=R1hruCxUdFVS8;`KNMd3);Lx9 zeaqi!OEk;j$t2}tf5Qm|FOdsh4lbaZ&L)+gj@a}FHr2plx7qiLM-rY6hr^M`+WU|y zD##xRe+feUB1Xi4)t&v)G`x+$jX6X}G!)U>H-HGCGQ{F3W7Wdm5OgeWr0_(6jhxy! zDqQ`gdEi#cyQoe8q5d^}BPRmC{KdOblh)>nNGH2LqErxW(Ud{Q$(sEh!j@(`mJ6j+jKmXg~F&!s| zMv2PpFDyw0j>7Dr01G<-_=^ACI{Lq4p#M;Wl`^vi)W>3fD5X~_tys_gK^(R@P^zAC z4D{W!SfdpD!UC5f5*cardole4j<)(o~P)iy&me?_-= z8al1KG)m=d@iL?M?{$eptp-9-BUa<#^<>*dBuRewC($IJ$ZmasvB8+q!8V5KDP%Cl zCNaxeD5m2@$58lRGIWE+YSb<@I0Rg8&clos>Nby_>~_c%*wW^WZT#ANn%GA~!y`3J zlr<%+W{lm|^WG3wRjFj{%Jy}hdv4|WQE$Vm|_)$_yN>iq3xpS5VAh!G zH=W0lBOr~SSsIT0foyh8JdnY3P%E3hdb`b#$4pqxJE*W46hj;Z(x0=rC5KYb156Jw zaW?J;sard~c6GWtz`S-&{|HGx+MP9ZXI_e3Iak90P`vu95UzZp{yM+g8PdSAY#hA< zoohi+e~&epaIcv@*ji?i2n55nSF#@&+GGHGkLa6EC+kGY1@$;@lfYV&hc+juO6}Ta zyQ0KHzOo!dRrih0eO2$nGky!)Wnva1xtTOp@(^&^09R=TG09Iv`gvfUoaC6!M~&&w zo6p4sa#Y9hU~;>TJ^OuBNOEtRsnVpPwqTcm2*oI}bR! z#hV1PbxPhRHm#oU$};!8!wbe1#P{cNkdlINKq+QcnGKPK0YYGeT7a~yyhU2qlFCCq zNP57;VxurA!JfkGc7ZZGVyZKLkhLm%)0m; z9y7|va|IROob+XD%aLMKmEu%tNOpE`Hw*Qp@~_hVMmsgsq0gNDd!^57W?)hCnFo8A zxHfrGH@{@?v_}2~#Q+$$`_D!Rf;LWozVd$o`5&uO&nl7M{N()}KMIvA#sY&om&aEH zBJc-rh;>MvRGePqhQCj+M#a}fP+0Gzez7rLcL*>K0QGYUQY0ybZC%xqqMf%YsB^N4 z@&t?$9-9ZuKL=J}9|OJgnk1s8@#oRA=uW|O)Rk3^fT&NxZO?=gQF&M#(%Fjn+2MF0 zH`OF5+l2IDw)yw@K3-kWhpUXP+>u{Yb=!Bnd$Oa_1-1IcAvdU54CIm%B!WcUYV#<8 zWZL7|AAiuZTKT%eT1^EOnut{8@EOS63db&id8mu>8zzaprg`_5Bc`kC!w*%=2#!)( z#?|;_a05LC0iYJHx&T_^cmw<;wcrUV+DBAm^zoQSSNT=9W^Wy7_ar+fqD-_q_KF}XnR1bSl^=Bb z2`Ry81u!e0soW|f7-0J9&luJrI(P2j+t)`%Bs(JD|603w9pQpIcoyORC*d4;S%C zDgAVu|20w=Mwl+3?m1)}{X=Q(<~)c)K4r*quR{Xyn9M*+3d_$;P0t@c6iYfGS3~P< zUs`=HF<%DG;j5b}?G`Kxb8x|FvO5<7LDyK+rap5%Bs0gvhdg*A!l~IpIoq}@(!}T_ zZ&A2G*=!9R+oO%6>EQ^ARCgv{5KOnSaGVb9=Jk|e)zx|53K7P3QKsh+mdX#hkjF1E3hSv-6o!_$Nt@q1
G?z*hJ()}#y?SHcqRQFglcY^d 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, CharSequence @@ -177,12 +178,14 @@ 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; @@ -207,12 +210,14 @@ 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; @@ -222,12 +227,14 @@ 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; @@ -237,12 +244,14 @@ 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; @@ -250,6 +259,7 @@ public StringBuilder append(boolean b) { @Override @IntrinsicCandidate + @SideEffectsOnly("this") public StringBuilder append(char c) { super.append(c); return this; @@ -257,24 +267,28 @@ 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; @@ -284,6 +298,7 @@ public StringBuilder append(double d) { * @since 1.5 */ @Override + @SideEffectsOnly("this") public StringBuilder appendCodePoint(int codePoint) { super.appendCodePoint(codePoint); return this; @@ -293,6 +308,7 @@ 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; @@ -302,6 +318,7 @@ 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; @@ -311,6 +328,7 @@ 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; @@ -320,6 +338,7 @@ 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) { @@ -331,6 +350,7 @@ 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; @@ -340,6 +360,7 @@ 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; @@ -349,6 +370,7 @@ 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; @@ -358,6 +380,7 @@ 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; @@ -367,6 +390,7 @@ 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) { @@ -378,6 +402,7 @@ 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; @@ -387,6 +412,7 @@ 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; @@ -396,6 +422,7 @@ 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; @@ -405,6 +432,7 @@ 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; @@ -414,6 +442,7 @@ 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; @@ -423,6 +452,7 @@ 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; @@ -453,6 +483,7 @@ 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/util/ArrayList.java b/src/java.base/share/classes/java/util/ArrayList.java index 6ba4982941e..f61398283b2 100644 --- a/src/java.base/share/classes/java/util/ArrayList.java +++ b/src/java.base/share/classes/java/util/ArrayList.java @@ -40,6 +40,7 @@ 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; @@ -471,6 +472,7 @@ 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); @@ -483,6 +485,7 @@ 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(); @@ -496,6 +499,7 @@ 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++; @@ -512,6 +516,7 @@ 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++; @@ -703,6 +708,7 @@ 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++; @@ -733,6 +739,7 @@ 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); diff --git a/src/java.base/share/classes/java/util/HashSet.java b/src/java.base/share/classes/java/util/HashSet.java index 60c0692c5c2..98d02eb218c 100644 --- a/src/java.base/share/classes/java/util/HashSet.java +++ b/src/java.base/share/classes/java/util/HashSet.java @@ -36,6 +36,7 @@ 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; @@ -237,6 +238,7 @@ 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; @@ -254,6 +256,7 @@ 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; } @@ -262,6 +265,7 @@ 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/Iterator.java b/src/java.base/share/classes/java/util/Iterator.java index 1e0d65349c6..873f17166e9 100644 --- a/src/java.base/share/classes/java/util/Iterator.java +++ b/src/java.base/share/classes/java/util/Iterator.java @@ -29,6 +29,7 @@ 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; @@ -86,6 +87,7 @@ 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/List.java b/src/java.base/share/classes/java/util/List.java index 31e2f761049..99a8bc5f398 100644 --- a/src/java.base/share/classes/java/util/List.java +++ b/src/java.base/share/classes/java/util/List.java @@ -41,6 +41,7 @@ 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; @@ -296,6 +297,7 @@ 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); @@ -320,6 +322,7 @@ 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); @@ -367,6 +370,7 @@ 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); @@ -397,6 +401,7 @@ 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); @@ -652,6 +657,7 @@ default void sort(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/Optional.java b/src/java.base/share/classes/java/util/Optional.java index 3ebeb85736b..5ec98f55bcf 100644 --- a/src/java.base/share/classes/java/util/Optional.java +++ b/src/java.base/share/classes/java/util/Optional.java @@ -297,7 +297,9 @@ public Optional filter(Predicate predicate) { * present, otherwise an empty {@code Optional} * @throws NullPointerException if the mapping function is {@code null} */ + @CFComment({"@SideEffectFree: the mapper must not have side effects."}) @OptionalPropagator + @SideEffectFree public Optional map(Function mapper) { Objects.requireNonNull(mapper); if (!isPresent()) { diff --git a/src/java.base/share/classes/java/util/Vector.java b/src/java.base/share/classes/java/util/Vector.java index 91fba253f06..03c27e191ab 100644 --- a/src/java.base/share/classes/java/util/Vector.java +++ b/src/java.base/share/classes/java/util/Vector.java @@ -38,6 +38,7 @@ 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; @@ -823,6 +824,7 @@ 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++; diff --git a/src/java.base/share/classes/java/util/stream/Collectors.java b/src/java.base/share/classes/java/util/stream/Collectors.java index 5a2a5fb06f9..790861b8284 100644 --- a/src/java.base/share/classes/java/util/stream/Collectors.java +++ b/src/java.base/share/classes/java/util/stream/Collectors.java @@ -281,6 +281,7 @@ public Set characteristics() { * @return a {@code Collector} which collects all the input elements into a * {@code List}, in encounter order */ + @SideEffectFree public static Collector> toList() { return new CollectorImpl<>(ArrayList::new, List::add, diff --git a/src/java.base/share/classes/java/util/stream/Stream.java b/src/java.base/share/classes/java/util/stream/Stream.java index 05bac437794..c63fcc78295 100644 --- a/src/java.base/share/classes/java/util/stream/Stream.java +++ b/src/java.base/share/classes/java/util/stream/Stream.java @@ -1122,6 +1122,8 @@ U reduce(U identity, * first result container. * @return the result of the reduction */ + @CFComment("@SideEffectFree: the supplied functions should not have side effects") + @SideEffectFree R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner); @@ -1178,6 +1180,8 @@ R collect(Supplier supplier, * @see #collect(Supplier, BiConsumer, BiConsumer) * @see Collectors */ + @CFComment("@SideEffectFree: the collector should not have side effects") + @SideEffectFree R collect(Collector collector); /** 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 new file mode 100644 index 00000000000..ab6a7dd1718 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/dataflow/qual/SideEffectsOnly.java @@ -0,0 +1,29 @@ +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(); +} From 8102a4d1a44859b4f1b29cb455c4411d5e02f34f Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sun, 14 Jul 2024 12:17:09 -0700 Subject: [PATCH 27/32] More `@SideEffectsOnly` annotations --- .../share/classes/java/io/BufferedReader.java | 3 ++ .../share/classes/java/lang/CharSequence.java | 5 +++ .../classes/java/lang/StackStreamFactory.java | 4 ++ .../lang/invoke/AbstractConstantGroup.java | 4 ++ src/java.base/share/classes/java/net/URL.java | 3 ++ .../classes/java/nio/charset/Charset.java | 3 ++ .../java/nio/file/FileTreeIterator.java | 4 ++ .../share/classes/java/nio/file/Files.java | 3 ++ .../share/classes/java/nio/file/Path.java | 3 ++ .../share/classes/java/util/AbstractList.java | 9 +++++ .../share/classes/java/util/AbstractMap.java | 5 +++ .../share/classes/java/util/ArrayDeque.java | 3 ++ .../share/classes/java/util/ArrayList.java | 4 ++ .../share/classes/java/util/Arrays.java | 3 ++ .../share/classes/java/util/Collections.java | 19 ++++++++++ .../share/classes/java/util/EnumMap.java | 2 + .../share/classes/java/util/Enumeration.java | 3 ++ .../share/classes/java/util/HashMap.java | 3 ++ .../share/classes/java/util/Hashtable.java | 3 ++ .../classes/java/util/IdentityHashMap.java | 3 ++ .../java/util/ImmutableCollections.java | 9 +++++ .../share/classes/java/util/JumboEnumSet.java | 3 ++ .../classes/java/util/LinkedHashMap.java | 3 ++ .../share/classes/java/util/LinkedList.java | 5 +++ .../share/classes/java/util/ListIterator.java | 2 + .../classes/java/util/PriorityQueue.java | 3 ++ .../classes/java/util/RegularEnumSet.java | 3 ++ .../share/classes/java/util/Scanner.java | 38 +++++++++++++++++++ .../classes/java/util/ServiceLoader.java | 11 ++++++ .../share/classes/java/util/Spliterators.java | 10 +++++ .../share/classes/java/util/TreeMap.java | 7 ++++ .../share/classes/java/util/Vector.java | 2 + .../share/classes/java/util/WeakHashMap.java | 3 ++ .../util/concurrent/ArrayBlockingQueue.java | 3 ++ .../util/concurrent/ConcurrentHashMap.java | 3 ++ .../concurrent/ConcurrentLinkedDeque.java | 3 ++ .../concurrent/ConcurrentLinkedQueue.java | 3 ++ .../concurrent/ConcurrentSkipListMap.java | 3 ++ .../util/concurrent/CopyOnWriteArrayList.java | 9 +++++ .../java/util/concurrent/DelayQueue.java | 3 ++ .../util/concurrent/LinkedBlockingDeque.java | 3 ++ .../util/concurrent/LinkedBlockingQueue.java | 3 ++ .../util/concurrent/LinkedTransferQueue.java | 3 ++ .../concurrent/PriorityBlockingQueue.java | 3 ++ .../ScheduledThreadPoolExecutor.java | 3 ++ .../classes/java/util/regex/Matcher.java | 3 ++ .../classes/java/util/regex/Pattern.java | 3 ++ .../share/classes/java/util/zip/ZipFile.java | 4 ++ .../classes/javax/security/auth/Subject.java | 3 ++ .../classes/sun/net/www/HeaderParser.java | 5 +++ .../classes/sun/net/www/MessageHeader.java | 5 +++ .../sun/security/jca/ProviderList.java | 5 +++ .../share/classes/sun/util/PreHashedMap.java | 7 ++++ .../sun/util/locale/StringTokenIterator.java | 5 +++ .../resources/ParallelListResourceBundle.java | 3 ++ .../classes/java/lang/ProcessEnvironment.java | 7 ++++ .../sun/nio/fs/UnixDirectoryStream.java | 5 +++ .../classes/sun/nio/fs/UnixFileSystem.java | 5 +++ .../classes/java/lang/ProcessEnvironment.java | 3 ++ .../sun/nio/fs/WindowsDirectoryStream.java | 5 +++ .../classes/sun/nio/fs/WindowsFileSystem.java | 5 +++ .../counter/perf/PerfInstrumentation.java | 6 +++ .../jdk/internal/net/http/HeaderParser.java | 5 +++ .../internal/net/http/RequestPublishers.java | 7 ++++ .../share/classes/java/sql/SQLException.java | 4 ++ .../keys/keyresolver/KeyResolver.java | 4 ++ .../keys/storage/StorageResolver.java | 5 +++ .../implementations/KeyStoreResolver.java | 5 +++ .../SingleCertificateResolver.java | 6 +++ .../security/signature/Reference.java | 4 ++ .../reference/ReferenceSubTreeData.java | 4 ++ .../xml/dsig/internal/dom/DOMSubTreeData.java | 4 ++ .../internal/generic/InstructionList.java | 3 ++ .../internal/impl/XMLStreamFilterImpl.java | 5 +++ .../internal/impl/XMLStreamReaderImpl.java | 4 ++ .../xerces/internal/impl/xs/XSModelImpl.java | 5 +++ .../internal/impl/xs/util/XSNamedMapImpl.java | 3 ++ .../impl/xs/util/XSObjectListImpl.java | 5 +++ .../internal/util/NamespaceSupport.java | 3 ++ .../util/XMLAttributesIteratorImpl.java | 5 +++ .../xpath/internal/jaxp/XPathNodesImpl.java | 4 ++ .../internal/stream/EventFilterSupport.java | 5 +++ .../internal/stream/XMLEventReaderImpl.java | 5 +++ .../stream/util/ReadOnlyIterator.java | 5 +++ .../javax/xml/catalog/CatalogImpl.java | 4 ++ .../javax/xml/stream/XMLEventReader.java | 5 +++ .../javax/xml/stream/XMLStreamReader.java | 5 +++ .../xml/stream/util/EventReaderDelegate.java | 5 +++ .../xml/stream/util/StreamReaderDelegate.java | 4 ++ .../nio/cs/ext/AbstractCharsetProvider.java | 6 +++ 90 files changed, 438 insertions(+) diff --git a/src/java.base/share/classes/java/io/BufferedReader.java b/src/java.base/share/classes/java/io/BufferedReader.java index 5f1969535cf..e441312156a 100644 --- a/src/java.base/share/classes/java/io/BufferedReader.java +++ b/src/java.base/share/classes/java/io/BufferedReader.java @@ -38,6 +38,7 @@ 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; @@ -580,6 +581,7 @@ public Stream lines(@GuardSatisfied BufferedReader this) { String nextLine = null; @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (nextLine != null) { @@ -595,6 +597,7 @@ 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 23f65fd72d0..6f668ed42d5 100644 --- a/src/java.base/share/classes/java/lang/CharSequence.java +++ b/src/java.base/share/classes/java/lang/CharSequence.java @@ -34,6 +34,7 @@ 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; @@ -167,11 +168,13 @@ public default IntStream chars() { class CharIterator implements PrimitiveIterator.OfInt { int cur = 0; + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cur < length(); } + @SideEffectsOnly("this") public int nextInt(@NonEmpty CharIterator this) { if (hasNext()) { return charAt(cur++); @@ -242,11 +245,13 @@ public void forEachRemaining(IntConsumer block) { } } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 4b142e5dba7..3e4518da8e5 100644 --- a/src/java.base/share/classes/java/lang/StackStreamFactory.java +++ b/src/java.base/share/classes/java/lang/StackStreamFactory.java @@ -25,6 +25,8 @@ package java.lang; 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; @@ -333,6 +335,7 @@ private int getNextBatch() { * * @see #tryNextFrame */ + @SideEffectsOnly("this") final Class nextFrame() { if (!hasNext()) { return null; @@ -348,6 +351,7 @@ final Class nextFrame() { * This skips hidden frames unless this StackWalker has * {@link Option#SHOW_REFLECT_FRAMES} */ + @Pure final boolean hasNext() { return peekFrame() != null; } 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 3f452e59b8b..f35de4e3b3e 100644 --- a/src/java.base/share/classes/java/lang/invoke/AbstractConstantGroup.java +++ b/src/java.base/share/classes/java/lang/invoke/AbstractConstantGroup.java @@ -27,6 +27,8 @@ 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; @@ -94,12 +96,14 @@ private AsIterator(ConstantGroup self, int start, int end, } @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return index < end; } @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 d5579c74aca..e69ad14ab78 100644 --- a/src/java.base/share/classes/java/net/URL.java +++ b/src/java.base/share/classes/java/net/URL.java @@ -33,6 +33,7 @@ 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; @@ -1341,11 +1342,13 @@ private boolean getNext() { return true; } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 4c48e91c634..0064dbbcf08 100644 --- a/src/java.base/share/classes/java/nio/charset/Charset.java +++ b/src/java.base/share/classes/java/nio/charset/Charset.java @@ -28,6 +28,7 @@ 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; @@ -356,11 +357,13 @@ private boolean getNext() { return true; } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 8035d7b29b8..6bdbf899b24 100644 --- a/src/java.base/share/classes/java/nio/file/FileTreeIterator.java +++ b/src/java.base/share/classes/java/nio/file/FileTreeIterator.java @@ -27,6 +27,8 @@ 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; @@ -100,6 +102,7 @@ private void fetchNextIfNeeded() { } @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (!walker.isOpen()) @@ -109,6 +112,7 @@ 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 c932a778c7b..2cb920d6d44 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -33,6 +33,7 @@ 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 java.io.BufferedReader; @@ -3874,6 +3875,7 @@ public static Path writeString(Path path, CharSequence csq, Charset cs, OpenOpti // Re-wrap DirectoryIteratorException to UncheckedIOException Iterator iterator = new Iterator<>() { @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { try { @@ -3882,6 +3884,7 @@ 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 73b9a0b1351..17d74768a5b 100644 --- a/src/java.base/share/classes/java/nio/file/Path.java +++ b/src/java.base/share/classes/java/nio/file/Path.java @@ -30,6 +30,7 @@ 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; @@ -952,12 +953,14 @@ default Iterator iterator() { private int i = 0; @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return (i < getNameCount()); } @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 e1f077c6c80..a16d1a1db3b 100644 --- a/src/java.base/share/classes/java/util/AbstractList.java +++ b/src/java.base/share/classes/java/util/AbstractList.java @@ -36,6 +36,7 @@ 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; @@ -382,11 +383,13 @@ private class Itr implements Iterator { */ int expectedModCount = modCount; + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor != size(); } + @SideEffectsOnly("this") public E next(@NonEmpty Itr this) { checkForComodification(); try { @@ -866,11 +869,13 @@ public ListIterator listIterator(int index) { private final ListIterator i = root.listIterator(offset + index); + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return nextIndex() < size; } + @SideEffectsOnly("this") public E next(/*@NonEmpty ListIterator this*/) { if (hasNext()) return i.next(); @@ -878,10 +883,12 @@ public E next(/*@NonEmpty ListIterator this*/) { throw new NoSuchElementException(); } + @Pure public boolean hasPrevious() { return previousIndex() >= 0; } + @SideEffectsOnly("this") public E previous() { if (hasPrevious()) return i.previous(); @@ -889,10 +896,12 @@ public E previous() { throw new NoSuchElementException(); } + @Pure public int nextIndex() { return i.nextIndex() - offset; } + @Pure public int previousIndex() { return i.previousIndex() - offset; } diff --git a/src/java.base/share/classes/java/util/AbstractMap.java b/src/java.base/share/classes/java/util/AbstractMap.java index 0325dccb016..2c58b3c3596 100644 --- a/src/java.base/share/classes/java/util/AbstractMap.java +++ b/src/java.base/share/classes/java/util/AbstractMap.java @@ -37,6 +37,7 @@ 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; @@ -380,11 +381,13 @@ public Iterator iterator() { return new Iterator() { private Iterator> i = entrySet().iterator(); + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return i.hasNext(); } + @SideEffectsOnly("this") public K next(/*@NonEmpty Iterator this*/) { return i.next().getKey(); } @@ -445,11 +448,13 @@ public Iterator iterator() { return new Iterator() { private Iterator> i = entrySet().iterator(); + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 fab432aaced..5509f53678f 100644 --- a/src/java.base/share/classes/java/util/ArrayDeque.java +++ b/src/java.base/share/classes/java/util/ArrayDeque.java @@ -48,6 +48,7 @@ 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; @@ -714,11 +715,13 @@ private class DeqIterator implements Iterator { DeqIterator() { cursor = head; } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 f61398283b2..b3a761c4302 100644 --- a/src/java.base/share/classes/java/util/ArrayList.java +++ b/src/java.base/share/classes/java/util/ArrayList.java @@ -1003,12 +1003,14 @@ private class Itr implements Iterator { // prevent creating a synthetic constructor Itr() {} + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") + @SideEffectsOnly("this") public E next(@NonEmpty Itr this) { checkForComodification(); int i = cursor; @@ -1339,12 +1341,14 @@ public ListIterator listIterator(@NonNegative int index) { int lastRet = -1; int expectedModCount = SubList.this.modCount; + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor != SubList.this.size; } @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 b3188ba6f09..911ff937032 100644 --- a/src/java.base/share/classes/java/util/Arrays.java +++ b/src/java.base/share/classes/java/util/Arrays.java @@ -44,6 +44,7 @@ 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; @@ -4292,12 +4293,14 @@ private static class ArrayItr implements Iterator { } @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor < a.length; } @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 2f8182b7d99..e230ce52003 100644 --- a/src/java.base/share/classes/java/util/Collections.java +++ b/src/java.base/share/classes/java/util/Collections.java @@ -44,6 +44,7 @@ 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; @@ -1092,8 +1093,10 @@ static class UnmodifiableCollection implements Collection, Serializable { return new Iterator() { private final Iterator i = c.iterator(); + @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(); @@ -1424,10 +1427,14 @@ public ListIterator listIterator(final int index) { private final ListIterator i = list.listIterator(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();} @@ -1763,10 +1770,12 @@ public Iterator> iterator() { return new Iterator>() { private final Iterator> i = c.iterator(); + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return i.hasNext(); } + @SideEffectsOnly("this") public Map.Entry next(/*@NonEmpty Iterator> this*/) { return new UnmodifiableEntry<>(i.next()); } @@ -3285,8 +3294,10 @@ public Iterator iterator() { // ListIterator with unsafe set() final Iterator it = c.iterator(); return new 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) { @@ -3679,8 +3690,10 @@ public ListIterator listIterator(final int index) { final ListIterator i = list.listIterator(index); return new ListIterator() { + @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(); } @@ -4001,8 +4014,10 @@ public Iterator> iterator() { final Iterator> i = s.iterator(); return new 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*/) { @@ -4454,8 +4469,10 @@ private static class EmptyIterator implements Iterator { static final EmptyIterator EMPTY_ITERATOR = new EmptyIterator<>(); + @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 @@ -4994,10 +5011,12 @@ public static Set singleton(T o) { static Iterator singletonIterator(final E e) { return new Iterator() { private boolean hasNext = true; + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 78bad1dc660..794683ef40a 100644 --- a/src/java.base/share/classes/java/util/EnumMap.java +++ b/src/java.base/share/classes/java/util/EnumMap.java @@ -39,6 +39,7 @@ 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; @@ -567,6 +568,7 @@ private abstract class EnumMapIterator implements Iterator { // Index of last returned element, or -1 if none int lastReturnedIndex = -1; + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { while (index < vals.length && vals[index] == null) diff --git a/src/java.base/share/classes/java/util/Enumeration.java b/src/java.base/share/classes/java/util/Enumeration.java index 0f42fa94e1c..27b02681707 100644 --- a/src/java.base/share/classes/java/util/Enumeration.java +++ b/src/java.base/share/classes/java/util/Enumeration.java @@ -29,6 +29,7 @@ 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; /** @@ -125,10 +126,12 @@ public interface Enumeration { */ default Iterator asIterator() { return new Iterator<>() { + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") @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 ef22aa82d95..b6fbd742f4b 100644 --- a/src/java.base/share/classes/java/util/HashMap.java +++ b/src/java.base/share/classes/java/util/HashMap.java @@ -39,6 +39,7 @@ 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; @@ -1616,11 +1617,13 @@ abstract class HashIterator { } } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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/Hashtable.java b/src/java.base/share/classes/java/util/Hashtable.java index 3879f699979..7941919e96d 100644 --- a/src/java.base/share/classes/java/util/Hashtable.java +++ b/src/java.base/share/classes/java/util/Hashtable.java @@ -39,6 +39,7 @@ 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; @@ -1528,11 +1529,13 @@ public T nextElement(@NonEmpty Enumerator this) { } // Iterator methods + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 76c77d0f977..8239894e498 100644 --- a/src/java.base/share/classes/java/util/IdentityHashMap.java +++ b/src/java.base/share/classes/java/util/IdentityHashMap.java @@ -37,6 +37,7 @@ 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; @@ -745,6 +746,7 @@ private abstract class IdentityHashMapIterator implements Iterator { boolean indexValid; // To avoid unnecessary next computation Object[] traversalTable = table; // reference to main table or copy + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { Object[] tab = traversalTable; @@ -759,6 +761,7 @@ 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 0229f0efefd..8916b2246b2 100644 --- a/src/java.base/share/classes/java/util/ImmutableCollections.java +++ b/src/java.base/share/classes/java/util/ImmutableCollections.java @@ -34,6 +34,7 @@ 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; @@ -375,11 +376,13 @@ static final class ListItr implements ListIterator { isListIterator = true; } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor != size; } + @SideEffectsOnly("this") public E next(@NonEmpty ListItr this) { try { int i = cursor; @@ -846,12 +849,14 @@ public Iterator iterator() { private int idx = (e1 == EMPTY) ? 1 : 2; @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return idx > 0; } @Override + @SideEffectsOnly("this") @SuppressWarnings("unchecked") public E next(/*@NonEmpty Iterator this*/) { if (idx == 1) { @@ -982,12 +987,14 @@ private final class SetNIterator implements Iterator { } @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return remaining > 0; } @Override + @SideEffectsOnly("this") public E next(@NonEmpty SetNIterator this) { if (remaining > 0) { E element; @@ -1303,11 +1310,13 @@ class MapNIterator implements Iterator> { } @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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/JumboEnumSet.java b/src/java.base/share/classes/java/util/JumboEnumSet.java index 0a1e008a1ea..5ea2c67f19e 100644 --- a/src/java.base/share/classes/java/util/JumboEnumSet.java +++ b/src/java.base/share/classes/java/util/JumboEnumSet.java @@ -35,6 +35,7 @@ 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; @@ -139,6 +140,7 @@ private class EnumSetIterator> implements Iterator { } @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { while (unseen == 0 && unseenIndex < elements.length - 1) @@ -148,6 +150,7 @@ 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 50be45dd72b..4b66d66c45c 100644 --- a/src/java.base/share/classes/java/util/LinkedHashMap.java +++ b/src/java.base/share/classes/java/util/LinkedHashMap.java @@ -36,6 +36,7 @@ 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; @@ -780,11 +781,13 @@ abstract class LinkedHashIterator { current = null; } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 b1b0db89f7c..f2d08390242 100644 --- a/src/java.base/share/classes/java/util/LinkedList.java +++ b/src/java.base/share/classes/java/util/LinkedList.java @@ -39,6 +39,7 @@ 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; @@ -912,11 +913,13 @@ private class ListItr implements ListIterator { nextIndex = index; } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return nextIndex < size; } + @SideEffectsOnly("this") public E next(@NonEmpty ListItr this) { checkForComodification(); if (!hasNext()) @@ -1024,10 +1027,12 @@ public Iterator descendingIterator() { */ private class DescendingIterator implements Iterator { private final ListItr itr = new ListItr(size()); + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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/ListIterator.java b/src/java.base/share/classes/java/util/ListIterator.java index 3d53f610169..d344296da53 100644 --- a/src/java.base/share/classes/java/util/ListIterator.java +++ b/src/java.base/share/classes/java/util/ListIterator.java @@ -31,6 +31,7 @@ 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; /** @@ -92,6 +93,7 @@ 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 e2c52871014..173882e8f00 100644 --- a/src/java.base/share/classes/java/util/PriorityQueue.java +++ b/src/java.base/share/classes/java/util/PriorityQueue.java @@ -39,6 +39,7 @@ 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; @@ -535,12 +536,14 @@ private final class Itr implements Iterator { Itr() {} // prevent access constructor creation + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor < size || (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 51ac8675a9a..743bde6a03c 100644 --- a/src/java.base/share/classes/java/util/RegularEnumSet.java +++ b/src/java.base/share/classes/java/util/RegularEnumSet.java @@ -36,6 +36,7 @@ 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; /** @@ -107,11 +108,13 @@ private class EnumSetIterator> implements Iterator { unseen = elements; } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 ef3bc7aa36d..e18c16a26ce 100644 --- a/src/java.base/share/classes/java/util/Scanner.java +++ b/src/java.base/share/classes/java/util/Scanner.java @@ -37,7 +37,9 @@ import org.checkerframework.checker.signedness.qual.PolySigned; import org.checkerframework.common.returnsreceiver.qual.This; 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.*; @@ -1452,6 +1454,7 @@ public String toString(@GuardSatisfied Scanner this) { * @throws IllegalStateException if this scanner is closed * @see java.util.Iterator */ + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext(@GuardSatisfied Scanner this) { ensureOpen(); @@ -1479,6 +1482,7 @@ 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(); @@ -1521,6 +1525,7 @@ public void remove(@GuardSatisfied Scanner this) { * the specified pattern * @throws IllegalStateException if this scanner is closed */ + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext(@GuardSatisfied Scanner this, String pattern) { return hasNext(patternCache.forName(pattern)); @@ -1540,6 +1545,7 @@ 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)); } @@ -1555,6 +1561,7 @@ public String next(@GuardSatisfied @NonEmpty Scanner this, String pattern) { * the specified pattern * @throws IllegalStateException if this scanner is closed */ + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext(@GuardSatisfied Scanner this, Pattern pattern) { ensureOpen(); @@ -1589,6 +1596,7 @@ 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) @@ -1623,6 +1631,7 @@ public String next(@GuardSatisfied @NonEmpty Scanner this, Pattern pattern) { * @return true if and only if this scanner has another line of input * @throws IllegalStateException if this scanner is closed */ + @Pure public boolean hasNextLine() { saveState(); @@ -1660,6 +1669,7 @@ 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()) @@ -1892,6 +1902,7 @@ public String nextLine(@GuardSatisfied @NonEmpty Scanner this) { * boolean value * @throws IllegalStateException if this scanner is closed */ + @Pure public boolean hasNextBoolean(@GuardSatisfied Scanner this) { return hasNext(boolPattern()); } @@ -1908,6 +1919,7 @@ 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())); @@ -1922,6 +1934,7 @@ public boolean nextBoolean(@GuardSatisfied @NonEmpty Scanner this) { * byte value * @throws IllegalStateException if this scanner is closed */ + @Pure public boolean hasNextByte(@GuardSatisfied Scanner this) { return hasNextByte(defaultRadix); } @@ -1941,6 +1954,7 @@ public boolean hasNextByte(@GuardSatisfied Scanner this) { * @throws IllegalStateException if this scanner is closed * @throws IllegalArgumentException if the radix is out of range */ + @Pure public boolean hasNextByte(@GuardSatisfied Scanner this, @Positive @IntRange(from = 2, to = 36) int radix) { setRadix(radix); boolean result = hasNext(integerPattern()); @@ -1972,6 +1986,7 @@ 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); } @@ -2007,6 +2022,7 @@ 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) @@ -2038,6 +2054,7 @@ public boolean hasNextByte(@GuardSatisfied Scanner this, @Positive @IntRange(fro * short value in the default radix * @throws IllegalStateException if this scanner is closed */ + @Pure public boolean hasNextShort(@GuardSatisfied Scanner this) { return hasNextShort(defaultRadix); } @@ -2057,6 +2074,7 @@ public boolean hasNextShort(@GuardSatisfied Scanner this) { * @throws IllegalStateException if this scanner is closed * @throws IllegalArgumentException if the radix is out of range */ + @Pure public boolean hasNextShort(@GuardSatisfied Scanner this, @Positive @IntRange(from = 2, to = 36) int radix) { setRadix(radix); boolean result = hasNext(integerPattern()); @@ -2088,6 +2106,7 @@ 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); } @@ -2123,6 +2142,7 @@ 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) @@ -2154,6 +2174,7 @@ public boolean hasNextShort(@GuardSatisfied Scanner this, @Positive @IntRange(fr * int value * @throws IllegalStateException if this scanner is closed */ + @Pure public boolean hasNextInt(@GuardSatisfied Scanner this) { return hasNextInt(defaultRadix); } @@ -2173,6 +2194,7 @@ public boolean hasNextInt(@GuardSatisfied Scanner this) { * @throws IllegalStateException if this scanner is closed * @throws IllegalArgumentException if the radix is out of range */ + @Pure public boolean hasNextInt(@GuardSatisfied Scanner this, @Positive @IntRange(from = 2, to = 36) int radix) { setRadix(radix); boolean result = hasNext(integerPattern()); @@ -2228,6 +2250,7 @@ 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); } @@ -2263,6 +2286,7 @@ 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) @@ -2294,6 +2318,7 @@ private String processIntegerToken(String token) { * long value * @throws IllegalStateException if this scanner is closed */ + @Pure public boolean hasNextLong(@GuardSatisfied Scanner this) { return hasNextLong(defaultRadix); } @@ -2313,6 +2338,7 @@ public boolean hasNextLong(@GuardSatisfied Scanner this) { * @throws IllegalStateException if this scanner is closed * @throws IllegalArgumentException if the radix is out of range */ + @Pure public boolean hasNextLong(@GuardSatisfied Scanner this, @Positive @IntRange(from = 2, to = 36) int radix) { setRadix(radix); boolean result = hasNext(integerPattern()); @@ -2344,6 +2370,7 @@ 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); } @@ -2379,6 +2406,7 @@ 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) @@ -2462,6 +2490,7 @@ private String processFloatToken(String token) { * float value * @throws IllegalStateException if this scanner is closed */ + @Pure public boolean hasNextFloat(@GuardSatisfied Scanner this) { setRadix(10); boolean result = hasNext(floatPattern()); @@ -2503,6 +2532,7 @@ 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)) { @@ -2529,6 +2559,7 @@ public float nextFloat(@GuardSatisfied @NonEmpty Scanner this) { * double value * @throws IllegalStateException if this scanner is closed */ + @Pure public boolean hasNextDouble(@GuardSatisfied Scanner this) { setRadix(10); boolean result = hasNext(floatPattern()); @@ -2570,6 +2601,7 @@ 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)) { @@ -2600,6 +2632,7 @@ public double nextDouble(@GuardSatisfied @NonEmpty Scanner this) { * {@code BigInteger} * @throws IllegalStateException if this scanner is closed */ + @Pure public boolean hasNextBigInteger(@GuardSatisfied Scanner this) { return hasNextBigInteger(defaultRadix); } @@ -2620,6 +2653,7 @@ public boolean hasNextBigInteger(@GuardSatisfied Scanner this) { * @throws IllegalStateException if this scanner is closed * @throws IllegalArgumentException if the radix is out of range */ + @Pure public boolean hasNextBigInteger(@GuardSatisfied Scanner this, @IntRange(from = 2, to = 36) int radix) { setRadix(radix); boolean result = hasNext(integerPattern()); @@ -2652,6 +2686,7 @@ 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); } @@ -2682,6 +2717,7 @@ 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) @@ -2713,6 +2749,7 @@ public BigInteger nextBigInteger(@GuardSatisfied @NonEmpty Scanner this, @IntRan * {@code BigDecimal} * @throws IllegalStateException if this scanner is closed */ + @Pure public boolean hasNextBigDecimal(@GuardSatisfied Scanner this) { setRadix(10); boolean result = hasNext(decimalPattern()); @@ -2747,6 +2784,7 @@ 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 9ba91eff06f..45e6b3d9a77 100644 --- a/src/java.base/share/classes/java/util/ServiceLoader.java +++ b/src/java.base/share/classes/java/util/ServiceLoader.java @@ -30,7 +30,9 @@ import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; 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; @@ -941,6 +943,7 @@ private Iterator providers(ModuleLayer layer) { } @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { while (nextProvider == null && nextError == null) { @@ -975,6 +978,7 @@ public boolean hasNext() { } @Override + @SideEffectsOnly("this") public Provider next(@NonEmpty LayerLookupIterator this) { if (!hasNext()) throw new NoSuchElementException(); @@ -1075,6 +1079,7 @@ private Iterator iteratorFor(ClassLoader loader) { } @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { while (nextProvider == null && nextError == null) { @@ -1279,6 +1284,7 @@ private Provider nextService() { @SuppressWarnings("removal") @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (acc == null) { @@ -1293,6 +1299,7 @@ public boolean hasNext() { @SuppressWarnings("removal") @Override + @SideEffectsOnly("this") public Provider next(@NonEmpty LazyClassPathLookupIterator this) { if (acc == null) { return nextService(); @@ -1317,11 +1324,13 @@ private Iterator> newLookupIterator() { Iterator> second = new LazyClassPathLookupIterator<>(); return new Iterator>() { @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return (first.hasNext() || second.hasNext()); } @Override + @SideEffectsOnly("this") public Provider next(/*@NonEmpty Iterator> this*/) { if (first.hasNext()) { return first.next(); @@ -1400,6 +1409,7 @@ private void checkReloadCount() { } @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { checkReloadCount(); @@ -1409,6 +1419,7 @@ 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 405f3ffcc03..453423b1698 100644 --- a/src/java.base/share/classes/java/util/Spliterators.java +++ b/src/java.base/share/classes/java/util/Spliterators.java @@ -26,7 +26,9 @@ 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.dataflow.qual.SideEffectsOnly; import java.util.function.Consumer; import java.util.function.DoubleConsumer; import java.util.function.IntConsumer; @@ -685,6 +687,7 @@ public void accept(T t) { } @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (!valueReady) @@ -693,6 +696,7 @@ public boolean hasNext() { } @Override + @SideEffectsOnly("this") public T next(@NonEmpty Adapter this) { if (!valueReady && !hasNext()) throw new NoSuchElementException(); @@ -745,6 +749,7 @@ public void accept(int t) { } @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (!valueReady) @@ -753,6 +758,7 @@ public boolean hasNext() { } @Override + @SideEffectsOnly("this") public int nextInt(@NonEmpty Adapter this) { if (!valueReady && !hasNext()) throw new NoSuchElementException(); @@ -801,6 +807,7 @@ public void accept(long t) { } @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (!valueReady) @@ -809,6 +816,7 @@ public boolean hasNext() { } @Override + @SideEffectsOnly("this") public long nextLong(@NonEmpty Adapter this) { if (!valueReady && !hasNext()) throw new NoSuchElementException(); @@ -857,6 +865,7 @@ public void accept(double t) { } @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (!valueReady) @@ -865,6 +874,7 @@ 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 9e305916785..b9cd216b714 100644 --- a/src/java.base/share/classes/java/util/TreeMap.java +++ b/src/java.base/share/classes/java/util/TreeMap.java @@ -38,6 +38,7 @@ 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; @@ -1525,11 +1526,13 @@ abstract class PrivateEntryIterator implements Iterator { next = first; } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean hasNext() { return next != null; } + @SideEffectsOnly("this") final Entry nextEntry() { Entry e = next; if (e == null) @@ -1541,6 +1544,7 @@ final Entry nextEntry() { return e; } + @SideEffectsOnly("this") final Entry prevEntry() { Entry e = next; if (e == null) @@ -2072,11 +2076,13 @@ abstract class SubMapIterator implements Iterator { fenceKey = fence == null ? UNBOUNDED : fence.key; } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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) @@ -2088,6 +2094,7 @@ 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 03c27e191ab..fbe6d001a4d 100644 --- a/src/java.base/share/classes/java/util/Vector.java +++ b/src/java.base/share/classes/java/util/Vector.java @@ -1279,6 +1279,7 @@ private class Itr implements Iterator { int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { // Racy but within spec, since modifications are checked @@ -1286,6 +1287,7 @@ 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 82257b2a891..fa07b1e626a 100644 --- a/src/java.base/share/classes/java/util/WeakHashMap.java +++ b/src/java.base/share/classes/java/util/WeakHashMap.java @@ -38,6 +38,7 @@ 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; @@ -808,6 +809,7 @@ private abstract class HashIterator implements Iterator { index = isEmpty() ? 0 : table.length; } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { Entry[] t = table; @@ -831,6 +833,7 @@ 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 7139660c9fc..31f674adb82 100644 --- a/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java @@ -45,6 +45,7 @@ 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; @@ -1197,6 +1198,7 @@ private void detach() { * fields (i.e. nextItem) that are not modified by update operations * triggered by queue modifications. */ + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (nextItem != null) @@ -1227,6 +1229,7 @@ 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 26dbff64f8e..4b69bb87304 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java @@ -50,6 +50,7 @@ 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; @@ -3472,7 +3473,9 @@ static class BaseIterator extends Traverser { advance(); } + @Pure public final boolean hasNext() { return next != null; } + @Pure public final boolean hasMoreElements() { return next != null; } public final void remove() { 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 4cbcdc902d5..3783fbfc4ab 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java @@ -47,6 +47,7 @@ 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; @@ -1432,11 +1433,13 @@ private void advance() { } } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 e7e1ed12b1e..d7c2c995192 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java @@ -46,6 +46,7 @@ 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; @@ -791,11 +792,13 @@ else if (p == q) } } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 d4de695aa46..c4850dbf8eb 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java @@ -46,6 +46,7 @@ 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.MethodHandles; import java.lang.invoke.VarHandle; @@ -2120,6 +2121,7 @@ abstract class Iter implements Iterator { advance(baseHead()); } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean hasNext() { return next != null; @@ -2962,6 +2964,7 @@ abstract class SubMapIter implements Iterator, Spliterator { } } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public final boolean hasNext() { return next != null; 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 a08a17903fb..650887a1266 100644 --- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java +++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java @@ -46,6 +46,7 @@ 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; @@ -1107,16 +1108,19 @@ static final class COWIterator implements ListIterator { snapshot = es; } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor < snapshot.length; } + @Pure public boolean hasPrevious() { return cursor > 0; } @SuppressWarnings("unchecked") + @SideEffectsOnly("this") public E next(@NonEmpty COWIterator this) { if (! hasNext()) throw new NoSuchElementException(); @@ -1124,16 +1128,19 @@ public E next(@NonEmpty COWIterator this) { } @SuppressWarnings("unchecked") + @SideEffectsOnly("this") public E previous() { if (! hasPrevious()) throw new NoSuchElementException(); return (E) snapshot[--cursor]; } + @Pure public int nextIndex() { return cursor; } + @Pure public int previousIndex() { return cursor - 1; } @@ -1567,11 +1574,13 @@ private static class COWSubListIterator implements ListIterator { it = l.listIterator(index + offset); } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 bb81eb21a49..4333cd6c25c 100644 --- a/src/java.base/share/classes/java/util/concurrent/DelayQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/DelayQueue.java @@ -45,6 +45,7 @@ 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; @@ -532,12 +533,14 @@ private class Itr implements Iterator { this.array = array; } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return cursor < array.length; } @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 0b8e7563fa9..822a8841883 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java @@ -45,6 +45,7 @@ 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; @@ -1096,11 +1097,13 @@ private Node succ(Node p) { } } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 916548afc84..4ad69f1b92d 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java @@ -44,6 +44,7 @@ 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; @@ -797,11 +798,13 @@ private class Itr implements Iterator { } } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 5fb7e1386fa..42e88dc63b1 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java @@ -45,6 +45,7 @@ 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 java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; @@ -913,11 +914,13 @@ else if (p == (p = p.next)) { advance(null); } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 d14dc3a7c07..eb9e655b7a8 100644 --- a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java @@ -45,6 +45,7 @@ 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; @@ -870,11 +871,13 @@ final class Itr implements Iterator { this.array = array; } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 764b24f6333..906e2831349 100644 --- a/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java +++ b/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java @@ -42,6 +42,7 @@ import org.checkerframework.checker.nullness.qual.PolyNull; import org.checkerframework.checker.signedness.qual.UnknownSignedness; import org.checkerframework.dataflow.qual.Pure; +import org.checkerframework.dataflow.qual.SideEffectsOnly; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; @@ -1343,11 +1344,13 @@ private class Itr implements Iterator { this.array = array; } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") 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 dc477594b56..0cf7838712e 100644 --- a/src/java.base/share/classes/java/util/regex/Matcher.java +++ b/src/java.base/share/classes/java/util/regex/Matcher.java @@ -35,6 +35,7 @@ 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; @@ -1339,6 +1340,7 @@ class MatchResultIterator implements Iterator { String textAsString; @Override + @SideEffectsOnly("this") public MatchResult next(@NonEmpty MatchResultIterator this) { if (expectedCount >= 0 && expectedCount != modCount) throw new ConcurrentModificationException(); @@ -1351,6 +1353,7 @@ public MatchResult next(@NonEmpty MatchResultIterator this) { } @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (state >= 0) 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 e6f4f5e3905..8d41a5b3d75 100644 --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -35,6 +35,7 @@ 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; @@ -5870,6 +5871,7 @@ 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(); @@ -5884,6 +5886,7 @@ public String next(@NonEmpty MatcherIterator this) { } } + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { if (matcher == null) { 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 cb4617c3ad5..c33dc0389c8 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -36,6 +36,7 @@ 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; @@ -506,18 +507,21 @@ public boolean hasMoreElements() { } @Override + @Pure @EnsuresNonEmptyIf(result = true, expression = "this") public boolean hasNext() { return i < entryCount; } @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 d67850140cd..aff92e6ed5f 100644 --- a/src/java.base/share/classes/javax/security/auth/Subject.java +++ b/src/java.base/share/classes/javax/security/auth/Subject.java @@ -34,6 +34,7 @@ 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.*; @@ -1126,9 +1127,11 @@ public Iterator iterator() { return new Iterator() { ListIterator i = list.listIterator(0); + @Pure @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/sun/net/www/HeaderParser.java b/src/java.base/share/classes/sun/net/www/HeaderParser.java index a4b2ab50497..4dd84fb1e63 100644 --- a/src/java.base/share/classes/sun/net/www/HeaderParser.java +++ b/src/java.base/share/classes/sun/net/www/HeaderParser.java @@ -25,6 +25,9 @@ package sun.net.www; +import org.checkerframework.dataflow.qual.Pure; +import org.checkerframework.dataflow.qual.SideEffectsOnly; + import java.util.Iterator; /* This is useful for the nightmare of parsing multi-part HTTP/RFC822 headers @@ -199,9 +202,11 @@ class ParserIterator implements Iterator { ParserIterator (boolean returnValue) { returnsValue = returnValue; } + @Pure public boolean hasNext () { return index iterator() { return new Iterator() { int index; + @Pure public boolean hasNext() { return tryGet(index) != null; } + @SideEffectsOnly("this") public Service next() { Service s = tryGet(index); if (s == null) { diff --git a/src/java.base/share/classes/sun/util/PreHashedMap.java b/src/java.base/share/classes/sun/util/PreHashedMap.java index 724af5412ef..75fdebcd05c 100644 --- a/src/java.base/share/classes/sun/util/PreHashedMap.java +++ b/src/java.base/share/classes/sun/util/PreHashedMap.java @@ -25,6 +25,9 @@ package sun.util; +import org.checkerframework.dataflow.qual.Pure; +import org.checkerframework.dataflow.qual.SideEffectsOnly; + import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -201,12 +204,14 @@ private boolean findNext() { return true; } + @Pure public boolean hasNext() { if (cur != null) return true; return findNext(); } + @SideEffectsOnly("this") public String next() { if (cur == null) { if (!findNext()) @@ -237,10 +242,12 @@ public Iterator> iterator() { return new Iterator>() { final Iterator i = keySet().iterator(); + @Pure public boolean hasNext() { return i.hasNext(); } + @SideEffectsOnly("this") public Map.Entry 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 f66bfd53752..7d0ab209641 100644 --- a/src/java.base/share/classes/sun/util/locale/StringTokenIterator.java +++ b/src/java.base/share/classes/sun/util/locale/StringTokenIterator.java @@ -30,6 +30,9 @@ */ package sun.util.locale; +import org.checkerframework.dataflow.qual.Pure; +import org.checkerframework.dataflow.qual.SideEffectsOnly; + public class StringTokenIterator { private String text; private String dlms; // null if a single char delimiter @@ -71,6 +74,7 @@ public boolean isDone() { return done; } + @SideEffectsOnly("this") public String next() { if (hasNext()) { start = end + 1; @@ -84,6 +88,7 @@ public String next() { return token; } + @Pure public boolean hasNext() { return (end < text.length()); } 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 2bb733edbc1..e372d57d222 100644 --- a/src/java.base/share/classes/sun/util/resources/ParallelListResourceBundle.java +++ b/src/java.base/share/classes/sun/util/resources/ParallelListResourceBundle.java @@ -28,6 +28,7 @@ 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; @@ -224,6 +225,7 @@ public Iterator iterator() { private boolean usingParent; @Override + @Pure public boolean hasNext() { if (itr.hasNext()) { return true; @@ -238,6 +240,7 @@ 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 2c394209723..11a552495ec 100644 --- a/src/java.base/unix/classes/java/lang/ProcessEnvironment.java +++ b/src/java.base/unix/classes/java/lang/ProcessEnvironment.java @@ -55,6 +55,7 @@ package java.lang; import org.checkerframework.dataflow.qual.Pure; +import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.io.*; import java.util.*; @@ -333,7 +334,9 @@ private static class StringEntrySet public Iterator> iterator() { return new Iterator>() { Iterator> i = s.iterator(); + @Pure public boolean hasNext() {return i.hasNext();} + @SideEffectsOnly("this") public Map.Entry next() { return new StringEntry(i.next()); } @@ -378,7 +381,9 @@ private static class StringValues public Iterator iterator() { return new 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();} }; @@ -407,7 +412,9 @@ private static class StringKeySet extends AbstractSet { public Iterator iterator() { return new 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 44b1c70abbb..f462dfd2258 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixDirectoryStream.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixDirectoryStream.java @@ -25,6 +25,9 @@ package sun.nio.fs; +import org.checkerframework.dataflow.qual.Pure; +import org.checkerframework.dataflow.qual.SideEffectsOnly; + import java.nio.file.*; import java.util.Iterator; import java.util.NoSuchElementException; @@ -193,6 +196,7 @@ private Path readNextEntry() { } @Override + @Pure public synchronized boolean hasNext() { if (nextEntry == null && !atEof) nextEntry = readNextEntry(); @@ -200,6 +204,7 @@ 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 b9f45d8a107..0e514ac552d 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java @@ -25,6 +25,9 @@ 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.*; import java.nio.file.spi.*; @@ -214,6 +217,7 @@ private FileStore readNext() { } @Override + @Pure public synchronized boolean hasNext() { if (next != null) return true; @@ -222,6 +226,7 @@ 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 dd469444a4f..80fccfd2861 100644 --- a/src/java.base/windows/classes/java/lang/ProcessEnvironment.java +++ b/src/java.base/windows/classes/java/lang/ProcessEnvironment.java @@ -64,6 +64,7 @@ package java.lang; import org.checkerframework.dataflow.qual.Pure; +import org.checkerframework.dataflow.qual.SideEffectsOnly; import java.io.*; import java.util.*; @@ -142,7 +143,9 @@ private static class CheckedEntrySet public Iterator> iterator() { return new 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 cf4933eca7a..0916f458799 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsDirectoryStream.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsDirectoryStream.java @@ -25,6 +25,9 @@ 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; import java.util.Iterator; @@ -204,6 +207,7 @@ private Path readNextEntry() { } @Override + @Pure public synchronized boolean hasNext() { if (nextEntry == null && !atEof) nextEntry = readNextEntry(); @@ -211,6 +215,7 @@ 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 967c0da0fac..91184da6616 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystem.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystem.java @@ -25,6 +25,9 @@ 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.*; import java.nio.file.spi.*; @@ -158,6 +161,7 @@ private FileStore readNext() { } @Override + @Pure public synchronized boolean hasNext() { if (next != null) return true; @@ -166,6 +170,7 @@ 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 40c31aacc32..9091b6aa347 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 @@ -25,6 +25,10 @@ package sun.management.counter.perf; +import org.checkerframework.dataflow.qual.Pure; +import org.checkerframework.dataflow.qual.SideEffectsOnly; + + import sun.management.counter.*; import java.nio.*; import java.util.*; @@ -76,10 +80,12 @@ void rewind() { map = new TreeMap<>(); } + @Pure 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 b8eb2ca6f6f..099f323266d 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 @@ -25,6 +25,9 @@ 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; import java.util.NoSuchElementException; @@ -200,10 +203,12 @@ class ParserIterator implements Iterator { returnsValue = returnValue; } @Override + @Pure 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 38241a4ff74..8a84c598827 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 @@ -25,6 +25,9 @@ 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; import java.io.FilePermission; @@ -130,11 +133,13 @@ class ByteBufferIterator implements Iterator { final ConcurrentLinkedQueue buffers = new ConcurrentLinkedQueue<>(); final Iterator iterator = content.iterator(); @Override + @Pure public boolean hasNext() { return !buffers.isEmpty() || iterator.hasNext(); } @Override + @SideEffectsOnly("this") public ByteBuffer next() { ByteBuffer buffer = buffers.poll(); while (buffer == null) { @@ -433,6 +438,7 @@ private void closeStream() { } @Override + @Pure public synchronized boolean hasNext() { if (need2Read) { try { @@ -454,6 +460,7 @@ 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 e2925760e38..1142b6c9f1e 100644 --- a/src/java.sql/share/classes/java/sql/SQLException.java +++ b/src/java.sql/share/classes/java/sql/SQLException.java @@ -26,6 +26,8 @@ package java.sql; 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; @@ -323,12 +325,14 @@ public Iterator iterator() { SQLException nextException = firstException.getNextException(); Throwable cause = firstException.getCause(); + @Pure public boolean hasNext() { if(firstException != null || nextException != null || cause != null) return true; 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 7aa9a30128a..f368cebb151 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 @@ -31,6 +31,8 @@ import java.util.concurrent.CopyOnWriteArrayList; 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; @@ -295,10 +297,12 @@ public ResolverIterator(List list) { it = res.iterator(); } + @Pure 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 2da744cad8c..18230035d56 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 @@ -22,6 +22,9 @@ */ 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; import java.security.cert.X509Certificate; @@ -133,6 +136,7 @@ public StorageResolverIterator(Iterator resolvers) { } /** {@inheritDoc} */ + @Pure public boolean hasNext() { if (currentResolver == null) { return false; @@ -147,6 +151,7 @@ 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 6f7ff7deb92..98984652a7c 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 @@ -22,6 +22,9 @@ */ 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; import java.security.cert.Certificate; @@ -103,11 +106,13 @@ public KeyStoreIterator(KeyStore keyStore) { } /** {@inheritDoc} */ + @Pure public boolean hasNext() { return this.i < this.certs.size(); } /** {@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 2b57b3c4e2c..40c1e22c689 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 @@ -22,6 +22,9 @@ */ 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; import java.util.Iterator; @@ -71,11 +74,14 @@ public InternalIterator(X509Certificate x509cert) { } /** {@inheritDoc} */ + @Pure public boolean hasNext() { + return !this.alreadyReturned; } /** {@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 384436b7b4e..211b5168238 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 @@ -52,6 +52,8 @@ import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver; 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; @@ -618,11 +620,13 @@ public Iterator iterator() { final Iterator sIterator = s.iterator(); @Override + @Pure public boolean hasNext() { return sIterator.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 215206015f8..c4ccc6336db 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 @@ -30,6 +30,8 @@ import java.util.List; 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; @@ -78,6 +80,7 @@ static class DelayedNodeIterator implements Iterator { this.withComments = !excludeComments; } + @Pure public boolean hasNext() { if (nodeSet == null) { nodeSet = dereferenceSameDocumentURI(root); @@ -86,6 +89,7 @@ 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 404942e72bf..78a03652f44 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 @@ -31,6 +31,8 @@ import java.util.List; 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; @@ -79,6 +81,7 @@ static class DelayedNodeIterator implements Iterator { this.withComments = !excludeComments; } + @Pure public boolean hasNext() { if (nodeSet == null) { nodeSet = dereferenceSameDocumentURI(root); @@ -87,6 +90,7 @@ 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 9eb8762c17a..ff99033d8ca 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,6 +20,7 @@ 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; @@ -1033,6 +1034,7 @@ public Iterator iterator() { private InstructionHandle ih = start; @Override + @SideEffectsOnly("this") public InstructionHandle next() throws NoSuchElementException { if (ih == null) { throw new NoSuchElementException(); @@ -1048,6 +1050,7 @@ public void remove() { } @Override + @Pure public boolean hasNext() { return ih != null; } 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 127e2c05479..6e7b4359056 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 @@ -25,6 +25,9 @@ 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; import javax.xml.stream.XMLStreamException; @@ -94,6 +97,7 @@ protected void setStreamFilter(StreamFilter sf){ * @return * @throws XMLStreamException */ + @SideEffectsOnly("this") public int next() throws XMLStreamException { if (fStreamAdvancedByHasNext && fEventAccepted) { fStreamAdvancedByHasNext = false; @@ -132,6 +136,7 @@ public int nextTag() throws XMLStreamException { * @throws XMLStreamException * @return */ + @Pure public boolean hasNext() throws XMLStreamException { if (fStreamReader.hasNext()) { if (!fEventAccepted) { 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 747bd9bc4f7..efd888ab9d7 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 @@ -25,6 +25,9 @@ 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; import com.sun.org.apache.xerces.internal.util.SymbolTable; @@ -516,6 +519,7 @@ public boolean hasName() { * @throws XMLStreamException * @return */ + @Pure public boolean hasNext() throws XMLStreamException { //the scanner returns -1 when it detects a broken stream if (fEventType == -1) { 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 43fb3a155a9..e328cd63ba0 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 @@ -20,6 +20,9 @@ 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; import com.sun.org.apache.xerces.internal.impl.xs.util.XSNamedMap4Types; @@ -812,9 +815,11 @@ private final class XSNamespaceItemListIterator implements ListIterator> entrySet() { public Iterator> iterator() { return new Iterator>() { private int index = 0; + @Pure 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 cab3a71a487..1b618554f28 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,6 +21,7 @@ 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; @@ -47,9 +48,11 @@ public class XSObjectListImpl extends AbstractList implements XSObject public static final XSObjectListImpl EMPTY_LIST = new XSObjectListImpl(new XSObject[0], 0); private static final ListIterator EMPTY_ITERATOR = new EmptyIterator(); static class EmptyIterator implements ListIterator { + @Pure public boolean hasNext() { return false; } + @SideEffectsOnly("this") public XSObject next() { throw new NoSuchElementException(); } @@ -231,9 +234,11 @@ private final class XSObjectListIterator implements ListIterator { public XSObjectListIterator(int index) { this.index = index; } + @Pure 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 f7194dbe420..5ca84d15b1c 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,6 +21,7 @@ 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; @@ -371,6 +372,7 @@ public IteratorPrefixes(String [] prefixes, int size) { /** * @see java.util.Enumeration#hasMoreElements() */ + @Pure public boolean hasNext() { return (counter < size); } @@ -378,6 +380,7 @@ 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 422c80b6420..9d04ba7cc86 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 @@ -25,6 +25,9 @@ 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; @@ -55,10 +58,12 @@ public class XMLAttributesIteratorImpl extends XMLAttributesImpl implements public XMLAttributesIteratorImpl() { } + @Pure 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 14c291fc94d..d48abf0d23b 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 @@ -29,6 +29,8 @@ import javax.xml.xpath.XPathException; 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; @@ -56,6 +58,7 @@ class NodeSetIterator implements Iterator { NodeSetIterator(Class elementType) { this.elementType = elementType; } + @Pure public boolean hasNext() { if (nodeList != null) { return currentIndex < nodeList.getLength(); @@ -64,6 +67,7 @@ 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 90c68836bf9..c02d2ed2d1d 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 @@ -25,6 +25,9 @@ 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; import javax.xml.stream.XMLEventReader; @@ -47,6 +50,7 @@ public EventFilterSupport(XMLEventReader eventReader, EventFilter eventFilter) { fEventFilter = eventFilter; } + @SideEffectsOnly("this") public Object next(){ try{ return nextEvent(); @@ -55,6 +59,7 @@ public Object next(){ } } + @Pure public boolean hasNext(){ try{ return peek() != null ? true : false ; 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 04181ba4b51..1f96b7112cd 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 @@ -25,6 +25,9 @@ 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; import javax.xml.stream.XMLInputFactory; @@ -56,6 +59,7 @@ public XMLEventReaderImpl(XMLStreamReader reader) throws XMLStreamException { } + @Pure public boolean hasNext() { //if we have the peeked event return 'true' if(fPeekedEvent != null)return true; @@ -71,6 +75,7 @@ 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 3106d15742e..aa1fc45aacf 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 @@ -29,6 +29,9 @@ * @author K.Venugopal ,Neeraj Bajaj Sun Microsystems. */ +import org.checkerframework.dataflow.qual.Pure; +import org.checkerframework.dataflow.qual.SideEffectsOnly; + import java.util.Iterator; public class ReadOnlyIterator implements Iterator { @@ -43,6 +46,7 @@ public ReadOnlyIterator(Iterator itr){ } @Override + @Pure public boolean hasNext() { if(iterator != null) return iterator.hasNext(); @@ -50,6 +54,7 @@ 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 db0f2b7f1f8..e5cf4573374 100644 --- a/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java +++ b/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java @@ -46,6 +46,8 @@ import javax.xml.parsers.ParserConfigurationException; 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; /** @@ -338,6 +340,7 @@ public Stream catalogs() { int nextCatalogIndex = 0; @Override + @Pure public boolean hasNext() { if (nextCatalog != null) { return true; @@ -348,6 +351,7 @@ 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 93d2779d400..3a951d9e3e4 100644 --- a/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java +++ b/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java @@ -25,6 +25,9 @@ package javax.xml.stream; +import org.checkerframework.dataflow.qual.Pure; +import org.checkerframework.dataflow.qual.SideEffectsOnly; + import javax.xml.stream.events.XMLEvent; import java.util.Iterator; @@ -51,6 +54,7 @@ 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; /** @@ -59,6 +63,7 @@ public interface XMLEventReader extends Iterator { * @return true if the event reader has more events, false otherwise */ @Override + @Pure public boolean hasNext(); /** 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 c2a230fe285..a2067a2c8f1 100644 --- a/src/java.xml/share/classes/javax/xml/stream/XMLStreamReader.java +++ b/src/java.xml/share/classes/javax/xml/stream/XMLStreamReader.java @@ -25,6 +25,9 @@ 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; @@ -298,6 +301,7 @@ 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; /** @@ -308,6 +312,7 @@ public interface XMLStreamReader extends XMLStreamConstants { * @return true if there are more events, false otherwise * @throws XMLStreamException if there is a fatal error detecting the next state */ + @Pure public boolean hasNext() 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 b7600ac5f55..f83aa47c7a2 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 @@ -25,6 +25,9 @@ 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; import javax.xml.stream.XMLStreamException; @@ -83,10 +86,12 @@ public XMLEvent nextEvent() return reader.nextEvent(); } + @SideEffectsOnly("this") public Object next() { return reader.next(); } + @Pure public boolean hasNext() { return reader.hasNext(); 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 f94d1db7546..0865afaf040 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 @@ -25,6 +25,9 @@ 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; import javax.xml.stream.XMLStreamReader; @@ -102,6 +105,7 @@ public void require(int type, String namespaceURI, String localName) reader.require(type,namespaceURI,localName); } + @Pure public boolean hasNext() throws XMLStreamException { 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 6c24819bd1b..fc0ac09f8ac 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 @@ -25,6 +25,10 @@ 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; import java.nio.charset.spi.CharsetProvider; @@ -179,10 +183,12 @@ public final Iterator charsets() { return new Iterator() { Iterator i = ks.iterator(); + @Pure public boolean hasNext() { return i.hasNext(); } + @SideEffectsOnly("this") public Charset next() { String csn = i.next(); synchronized (AbstractCharsetProvider.this) { From f4d40f209b5b6e229199a6c134b105d54d9241dd Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 15 Aug 2024 11:28:33 -0700 Subject: [PATCH 28/32] Add `@Pure` annotation to `peek()` --- src/java.base/share/classes/java/io/ObjectInputStream.java | 4 ++++ src/java.base/share/classes/java/net/DatagramSocketImpl.java | 2 ++ src/java.base/share/classes/java/util/ArrayDeque.java | 2 ++ src/java.base/share/classes/java/util/Collections.java | 4 ++++ src/java.base/share/classes/java/util/LinkedList.java | 3 +++ src/java.base/share/classes/java/util/PriorityQueue.java | 1 + src/java.base/share/classes/java/util/Stack.java | 1 + .../classes/java/util/concurrent/ArrayBlockingQueue.java | 1 + .../classes/java/util/concurrent/ConcurrentLinkedDeque.java | 3 +++ .../classes/java/util/concurrent/ConcurrentLinkedQueue.java | 1 + .../share/classes/java/util/concurrent/DelayQueue.java | 1 + .../share/classes/java/util/concurrent/ForkJoinPool.java | 1 + .../classes/java/util/concurrent/LinkedBlockingDeque.java | 3 +++ .../classes/java/util/concurrent/LinkedBlockingQueue.java | 1 + .../classes/java/util/concurrent/LinkedTransferQueue.java | 1 + .../classes/java/util/concurrent/PriorityBlockingQueue.java | 1 + .../java/util/concurrent/ScheduledThreadPoolExecutor.java | 1 + .../share/classes/java/util/concurrent/SynchronousQueue.java | 1 + src/java.base/share/classes/java/util/jar/Manifest.java | 1 + src/java.base/share/classes/java/util/regex/Pattern.java | 3 +++ .../share/classes/javax/crypto/CryptoPolicyParser.java | 1 + .../jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java | 2 ++ .../share/classes/sun/security/provider/ConfigFile.java | 3 +++ .../share/classes/sun/security/provider/PolicyParser.java | 1 + .../share/classes/sun/security/util/DerInputStream.java | 3 +++ 25 files changed, 46 insertions(+) diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index 36424ea2533..a0c2393b9ec 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -33,6 +33,7 @@ import org.checkerframework.checker.mustcall.qual.MustCallAlias; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.signedness.qual.SignedPositive; +import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.framework.qual.AnnotatedFor; import java.io.ObjectInputFilter.Config; @@ -2857,6 +2858,7 @@ private static class PeekInputStream extends InputStream { * Peeks at next byte value in stream. Similar to read(), except * that it does not consume the read value. */ + @Pure int peek() throws IOException { if (peekb >= 0) { return peekb; @@ -3181,6 +3183,7 @@ int currentBlockRemaining() { * the stream, or -1 if the end of the stream/block data (if in block * data mode) has been reached. */ + @Pure int peek() throws IOException { if (blkmode) { if (pos == end) { @@ -3197,6 +3200,7 @@ int peek() throws IOException { * the stream, or throws EOFException if end of stream/block data has * been reached. */ + @Pure byte peekByte() throws IOException { int val = peek(); if (val < 0) { diff --git a/src/java.base/share/classes/java/net/DatagramSocketImpl.java b/src/java.base/share/classes/java/net/DatagramSocketImpl.java index 873c6b0a024..92d9ffa1cd4 100644 --- a/src/java.base/share/classes/java/net/DatagramSocketImpl.java +++ b/src/java.base/share/classes/java/net/DatagramSocketImpl.java @@ -26,6 +26,7 @@ package java.net; import org.checkerframework.checker.interning.qual.UsesObjectEquals; +import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.framework.qual.AnnotatedFor; import java.io.FileDescriptor; @@ -145,6 +146,7 @@ protected void disconnect() {} * to a currently unreachable destination. Note, there is no guarantee that the * exception will be thrown. */ + @Pure protected abstract int peek(InetAddress i) throws IOException; /** diff --git a/src/java.base/share/classes/java/util/ArrayDeque.java b/src/java.base/share/classes/java/util/ArrayDeque.java index 5509f53678f..75d6541dbd7 100644 --- a/src/java.base/share/classes/java/util/ArrayDeque.java +++ b/src/java.base/share/classes/java/util/ArrayDeque.java @@ -438,6 +438,7 @@ public E getLast(@GuardSatisfied @NonEmpty ArrayDeque this) { return elementAt(elements, head); } + @Pure public @Nullable E peekLast() { final Object[] es; return elementAt(es = elements, dec(tail, es.length)); @@ -581,6 +582,7 @@ public E element(@GuardSatisfied @NonEmpty ArrayDeque this) { * @return the head of the queue represented by this deque, or * {@code null} if this deque is empty */ + @Pure public @Nullable E peek() { return peekFirst(); } diff --git a/src/java.base/share/classes/java/util/Collections.java b/src/java.base/share/classes/java/util/Collections.java index e230ce52003..bed3d30cbef 100644 --- a/src/java.base/share/classes/java/util/Collections.java +++ b/src/java.base/share/classes/java/util/Collections.java @@ -3413,8 +3413,11 @@ static class CheckedQueue } public E element() {return queue.element();} + @Pure public boolean equals(Object o) {return o == this || c.equals(o);} + @Pure public int hashCode() {return c.hashCode();} + @Pure public E peek() {return queue.peek();} public E poll() {return queue.poll();} public E remove() {return queue.remove();} @@ -6008,6 +6011,7 @@ static class AsLIFOQueue extends AbstractQueue public boolean offer(E e) { return q.offerFirst(e); } public E poll() { return q.pollFirst(); } public E remove() { return q.removeFirst(); } + @Pure public E peek() { return q.peekFirst(); } public E element() { return q.getFirst(); } public void clear() { q.clear(); } diff --git a/src/java.base/share/classes/java/util/LinkedList.java b/src/java.base/share/classes/java/util/LinkedList.java index f2d08390242..976ba956783 100644 --- a/src/java.base/share/classes/java/util/LinkedList.java +++ b/src/java.base/share/classes/java/util/LinkedList.java @@ -680,6 +680,7 @@ Node node(@NonNegative int index) { * @return the head of this list, or {@code null} if this list is empty * @since 1.5 */ + @Pure public @Nullable E peek() { final Node f = first; return (f == null) ? null : f.item; @@ -762,6 +763,7 @@ public boolean offerLast(E e) { * if this list is empty * @since 1.6 */ + @Pure public @Nullable E peekFirst() { final Node f = first; return (f == null) ? null : f.item; @@ -775,6 +777,7 @@ public boolean offerLast(E e) { * if this list is empty * @since 1.6 */ + @Pure public @Nullable E peekLast() { final Node l = last; return (l == null) ? null : l.item; diff --git a/src/java.base/share/classes/java/util/PriorityQueue.java b/src/java.base/share/classes/java/util/PriorityQueue.java index 173882e8f00..649c8ff5712 100644 --- a/src/java.base/share/classes/java/util/PriorityQueue.java +++ b/src/java.base/share/classes/java/util/PriorityQueue.java @@ -353,6 +353,7 @@ public boolean offer(E e) { return true; } + @Pure public @Nullable E peek(@GuardSatisfied PriorityQueue this) { return (E) queue[0]; } diff --git a/src/java.base/share/classes/java/util/Stack.java b/src/java.base/share/classes/java/util/Stack.java index c3b4dd4a4a2..6bb22a593e6 100644 --- a/src/java.base/share/classes/java/util/Stack.java +++ b/src/java.base/share/classes/java/util/Stack.java @@ -103,6 +103,7 @@ public synchronized E pop(@GuardSatisfied Stack this) { * of the {@code Vector} object). * @throws EmptyStackException if this stack is empty. */ + @Pure public synchronized E peek() { int len = size(); 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 31f674adb82..c4d99dd012d 100644 --- a/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java @@ -455,6 +455,7 @@ public E poll(long timeout, TimeUnit unit) throws InterruptedException { } } + @Pure public E peek() { final ReentrantLock lock = this.lock; lock.lock(); 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 3783fbfc4ab..2d8e66e2300 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java @@ -882,6 +882,7 @@ public boolean offerLast(E e) { return true; } + @Pure public @Nullable E peekFirst() { restart: for (;;) { E item; @@ -897,6 +898,7 @@ public boolean offerLast(E e) { } } + @Pure public @Nullable E peekLast() { restart: for (;;) { E item; @@ -1009,6 +1011,7 @@ public boolean add(E e) { } public @Nullable E poll() { return pollFirst(); } + @Pure public @Nullable E peek() { return peekFirst(); } /** 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 d7c2c995192..a8c029fdd3f 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java @@ -417,6 +417,7 @@ else if (p == q) } } + @Pure public @Nullable E peek() { restartFromHead: for (;;) { for (Node h = head, p = h, q;; p = q) { 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 4333cd6c25c..d619b0e085f 100644 --- a/src/java.base/share/classes/java/util/concurrent/DelayQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/DelayQueue.java @@ -316,6 +316,7 @@ public E take() throws InterruptedException { * @return the head of this queue, or {@code null} if this * queue is empty */ + @Pure public @Nullable E peek() { final ReentrantLock lock = this.lock; lock.lock(); diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java index 4e077ada4ae..43a0961cfd6 100644 --- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java @@ -1167,6 +1167,7 @@ final ForkJoinTask nextLocalTask() { /** * Returns next task, if one exists, in order specified by mode. */ + @Pure final ForkJoinTask peek() { VarHandle.acquireFence(); int cap; ForkJoinTask[] a; 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 822a8841883..d25e44d2d16 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java @@ -570,6 +570,7 @@ public E getLast(@NonEmpty LinkedBlockingDeque this) { return x; } + @Pure public @Nullable E peekFirst() { final ReentrantLock lock = this.lock; lock.lock(); @@ -580,6 +581,7 @@ public E getLast(@NonEmpty LinkedBlockingDeque this) { } } + @Pure public @Nullable E peekLast() { final ReentrantLock lock = this.lock; lock.lock(); @@ -706,6 +708,7 @@ public E element(@NonEmpty LinkedBlockingDeque this) { return getFirst(); } + @Pure public @Nullable E peek() { return peekFirst(); } 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 4ad69f1b92d..4336f5a701c 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java @@ -508,6 +508,7 @@ public E take() throws InterruptedException { return x; } + @Pure public @Nullable E peek() { final AtomicInteger count = this.count; if (count.get() == 0) 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 42e88dc63b1..f7293556771 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java @@ -1358,6 +1358,7 @@ public Iterator iterator() { return new Itr(); } + @Pure public E peek() { restartFromHead: for (;;) { for (Node p = head; p != null;) { 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 eb9e655b7a8..157be54e2d5 100644 --- a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java @@ -568,6 +568,7 @@ public E take() throws InterruptedException { return result; } + @Pure public @Nullable E peek() { final ReentrantLock lock = this.lock; lock.lock(); 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 906e2831349..3861899a7f2 100644 --- a/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java +++ b/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java @@ -1096,6 +1096,7 @@ public int remainingCapacity() { return Integer.MAX_VALUE; } + @Pure public RunnableScheduledFuture peek() { final ReentrantLock lock = this.lock; lock.lock(); 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 7039049aa9d..ff89b1915f7 100644 --- a/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java @@ -1034,6 +1034,7 @@ public boolean retainAll(Collection c) { * * @return {@code null} */ + @Pure public E peek() { return null; } diff --git a/src/java.base/share/classes/java/util/jar/Manifest.java b/src/java.base/share/classes/java/util/jar/Manifest.java index 7a431e63218..564c02de546 100644 --- a/src/java.base/share/classes/java/util/jar/Manifest.java +++ b/src/java.base/share/classes/java/util/jar/Manifest.java @@ -518,6 +518,7 @@ public int readLine(byte[] b, int off, int len) throws IOException { return total; } + @Pure public byte peek() throws IOException { if (pos == count) fill(); 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 8d41a5b3d75..8c750636c56 100644 --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -1917,6 +1917,7 @@ private void mark(int c) { /** * Peek the next character, and do not advance the cursor. */ + @Pure private int peek() { int ch = temp[cursor]; if (has(COMMENTS)) @@ -1965,6 +1966,7 @@ private int nextEscaped() { /** * If in xmode peek past whitespace and comments. */ + @Pure private int peekPastWhitespace(int ch) { while (ASCII.isSpace(ch) || ch == '#') { while (ASCII.isSpace(ch)) @@ -2006,6 +2008,7 @@ private int parsePastLine() { /** * xmode peek past comment to end of line. */ + @Pure private int peekPastLine() { int ch = temp[++cursor]; while (ch != 0 && !isLineSeparator(ch)) diff --git a/src/java.base/share/classes/javax/crypto/CryptoPolicyParser.java b/src/java.base/share/classes/javax/crypto/CryptoPolicyParser.java index 1894bd2813d..06b0ca35642 100644 --- a/src/java.base/share/classes/javax/crypto/CryptoPolicyParser.java +++ b/src/java.base/share/classes/javax/crypto/CryptoPolicyParser.java @@ -317,6 +317,7 @@ private boolean peekAndMatch(String expect) return false; } + @Pure private boolean peek(String expect) { boolean found = false; diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java index b34d5cc4bbb..b0b8f8295b6 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java @@ -58,6 +58,7 @@ */ package jdk.internal.org.objectweb.asm.commons; +import org.checkerframework.dataflow.qual.Pure; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -623,6 +624,7 @@ private Object popValue() { return stackFrame.remove(stackFrame.size() - 1); } + @Pure private Object peekValue() { return stackFrame.get(stackFrame.size() - 1); } diff --git a/src/java.base/share/classes/sun/security/provider/ConfigFile.java b/src/java.base/share/classes/sun/security/provider/ConfigFile.java index 7a389ed90f8..35c830cca1d 100644 --- a/src/java.base/share/classes/sun/security/provider/ConfigFile.java +++ b/src/java.base/share/classes/sun/security/provider/ConfigFile.java @@ -48,6 +48,8 @@ import static java.nio.charset.StandardCharsets.UTF_8; +import org.checkerframework.dataflow.qual.Pure; + /** * This class represents a default implementation for * {@code javax.security.auth.login.Configuration}. @@ -586,6 +588,7 @@ private String match(String expect) throws IOException { return value; } + @Pure private boolean peek(String expect) { switch (lookahead) { case ',': diff --git a/src/java.base/share/classes/sun/security/provider/PolicyParser.java b/src/java.base/share/classes/sun/security/provider/PolicyParser.java index addb1c8789b..bc740c915d3 100644 --- a/src/java.base/share/classes/sun/security/provider/PolicyParser.java +++ b/src/java.base/share/classes/sun/security/provider/PolicyParser.java @@ -687,6 +687,7 @@ private boolean peekAndMatch(String expect) } } + @Pure private boolean peek(String expect) { boolean found = false; diff --git a/src/java.base/share/classes/sun/security/util/DerInputStream.java b/src/java.base/share/classes/sun/security/util/DerInputStream.java index d937cf1ec2b..4281a38b995 100644 --- a/src/java.base/share/classes/sun/security/util/DerInputStream.java +++ b/src/java.base/share/classes/sun/security/util/DerInputStream.java @@ -25,6 +25,8 @@ package sun.security.util; +import org.checkerframework.dataflow.qual.Pure; + import java.io.InputStream; import java.io.IOException; import java.math.BigInteger; @@ -215,6 +217,7 @@ public DerValue[] getSet(int startLen, boolean implicit) throws IOException { } } + @Pure public int peekByte() throws IOException { if (pos == end) { throw new IOException("At end"); From 77fb5c6c588ce26fc4a32def3e7cb9c371e2168f Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Tue, 12 Nov 2024 08:29:06 -0500 Subject: [PATCH 29/32] Use jtreg from docker image --- azure-pipelines.yml | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 37a939ffff1..99fe98db787 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -15,12 +15,7 @@ jobs: ls -al env | sort displayName: show environment - - bash: | - wget https://builds.shipilev.net/jtreg/jtreg-6.2%2B1.zip -O /tmp/$USER/jtreg.zip - unzip /tmp/$USER/jtreg.zip -d /tmp/$USER/ - chmod +x /tmp/$USER/jtreg/bin/jtdiff /tmp/$USER/jtreg/bin/jtreg - displayName: download jtreg - - bash: pwd && ls && bash ./configure --with-jtreg=/tmp/$USER/jtreg --disable-warnings-as-errors + - bash: pwd && ls && bash ./configure --with-jtreg=/usr/share/jtreg --disable-warnings-as-errors displayName: configure - bash: make jdk timeoutInMinutes: 90 @@ -45,16 +40,11 @@ jobs: ls -al env | sort displayName: show environment - - bash: | - wget https://builds.shipilev.net/jtreg/jtreg-6.2%2B1.zip -O /tmp/$USER/jtreg.zip - unzip /tmp/$USER/jtreg.zip -d /tmp/$USER/ - chmod +x /tmp/$USER/jtreg/bin/jtdiff /tmp/$USER/jtreg/bin/jtreg - displayName: download jtreg - 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 ; \ + 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: | @@ -102,7 +92,7 @@ jobs: 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=/tmp/$USER/jtreg && bash ./configure --with-jtreg=/tmp/$USER/jtreg --disable-warnings-as-errors + - bash: cd ../jdk17u && export JT_HOME=/tmp/$USER/jtreg && bash ./configure --with-jtreg=/usr/share/jtreg --disable-warnings-as-errors displayName: configure - bash: cd ../jdk17u && make jdk displayName: make jdk From 6a8473e6d6a5fa1b16225af9286dc1fb452be834 Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Tue, 12 Nov 2024 08:30:44 -0500 Subject: [PATCH 30/32] Consistent env var --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 99fe98db787..458ab4486ea 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -92,7 +92,7 @@ jobs: 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=/tmp/$USER/jtreg && bash ./configure --with-jtreg=/usr/share/jtreg --disable-warnings-as-errors + - 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 From a129634a243ad3c257a0325e7f7a44f6040a128e Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Tue, 12 Nov 2024 22:01:44 -0500 Subject: [PATCH 31/32] Disable debuggin, remove duplication --- azure-pipelines.yml | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 458ab4486ea..f1b8e9a621f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,5 +1,5 @@ -variables: - system.debug: true +# variables: +# system.debug: true jobs: @@ -54,13 +54,6 @@ jobs: 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 - - 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 # 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". From 103ec21bf137db8bb1f68a79325c74e8532b1973 Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Tue, 12 Nov 2024 22:38:56 -0500 Subject: [PATCH 32/32] Run all tests at once --- azure-pipelines.yml | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f1b8e9a621f..9784c3888e0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -130,17 +130,8 @@ jobs: displayName: clone git-scripts - bash: /tmp/$USER/git-scripts/git-clone-related eisop 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 + - 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() @@ -162,17 +153,8 @@ jobs: displayName: clone git-scripts - bash: /tmp/$USER/git-scripts/git-clone-related eisop 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 + - bash: (cd ../checker-framework && checker/bin-devel/test-cftests-all.sh) + displayName: test-cftests-all.sh - job: test_cftests_all_jdk_latest timeoutInMinutes: 120