blob: 7e7d8b9cdc17e88ee9e1e17230cb98f1b71eb343 [file] [log] [blame]
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;
/**
* A method is called <em>deterministic</em> if it returns the same value (according to {@code ==})
* every time it is called with the same parameters and in the same environment. The parameters
* include the receiver, and the environment includes all of the Java heap (that is, all fields of
* all objects and all static variables).
*
* <p>Determinism refers to the return value during a non-exceptional execution. If a method throws
* an exception, the Throwable does not have to be exactly the same object on each invocation (and
* generally should not be, to capture the correct stack trace).
*
* <p>This annotation is important to pluggable type-checking because, after a call to a
* {@code @Deterministic} method, flow-sensitive type refinement can assume that anything learned
* about the first invocation is true about subsequent invocations (so long as no
* non-{@code @}{@link SideEffectFree} method call intervenes). For example, the following code
* never suffers a null pointer exception, so the Nullness Checker need not issue a warning:
*
* <pre>{@code
* if (x.myDeterministicMethod() != null) {
* x.myDeterministicMethod().hashCode();
* }
* }</pre>
*
* <p>Note that {@code @Deterministic} guarantees that the result is identical according to {@code
* ==}, <b>not</b> just equal according to {@code equals()}. This means that writing <code>
* {@literal @}Deterministic</code> on a method that returns a reference (including a String) is
* often erroneous unless the returned value is cached or interned.
*
* <p>Also see {@link Pure}, which means both deterministic and {@link SideEffectFree}.
*
* <p><b>Analysis:</b> The Checker Framework performs a conservative analysis to verify a
* {@code @Deterministic} annotation. The Checker Framework issues a warning if the method uses any
* of the following Java constructs:
*
* <ol>
* <li>Assignment to any expression, except for local variables (and method parameters).
* <li>A method invocation of a method that is not {@link Deterministic}.
* <li>Construction of a new object.
* <li>Catching any exceptions. This is to prevent a method to get a hold of newly created objects
* and using these objects (or some property thereof) to change their return value. For
* instance, the following method must be forbidden.
* <pre>
* {@code @Deterministic
* int f() {
* try {
* int b = 0;
* int a = 1/b;
* } catch (Throwable t) {
* return t.hashCode();
* }
* return 0;
* }
* }</pre>
* </ol>
*
* A constructor can be {@code @Pure}, but a constructor <em>invocation</em> is not deterministic
* since it returns a different new object each time. TODO: Side-effect-free constructors could be
* allowed to set their own fields.
*
* <p>Note that the rules for checking currently imply that every {@code Deterministic} method is
* also {@link SideEffectFree}. This might change in the future; in general, a deterministic method
* does not need to be side-effect-free.
*
* <p>These rules are conservative: any code that passes the checks is deterministic, but the
* Checker Framework may issue false positive warnings, for code that uses one of the forbidden
* constructs but is deterministic nonetheless.
*
* <p>In fact, the rules are so conservative that checking is currently disabled by default, but can
* be enabled via the {@code -AcheckPurityAnnotations} command-line option.
*
* <p>
*
* @checker_framework.manual #type-refinement-purity Side effects, determinism, purity, and
* flow-sensitive analysis
* @author Stefan Heule
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
public @interface Deterministic {}