org.checkerframework.dataflow.qual.Deterministic Maven / Gradle / Ivy
Show all versions of checker-qual7 Show documentation
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 deterministic 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).
*
* 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).
*
*
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:
*
*
{@code
* if (x.myDeterministicMethod() != null) {
* x.myDeterministicMethod().hashCode();
* }
* }
*
* Note that {@code @Deterministic} guarantees that the result is identical according to {@code
* ==}, not just equal according to {@code equals()}. This means that writing
* {@code @Deterministic} on a method that returns a reference (including a String) is often
* erroneous unless the returned value is cached or interned.
*
*
Also see {@link Pure}, which means both deterministic and {@link SideEffectFree}.
*
*
Analysis: 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:
*
*
* - Assignment to any expression, except for local variables (and method parameters).
*
- A method invocation of a method that is not {@link Deterministic}.
*
- Construction of a new object.
*
- Catching any exceptions. This restriction prevents a method from obtaining a reference to a
* newly-created exception object and using these objects (or some property thereof) to change
* the method's return value. For instance, the following method must be forbidden.
*
*
@Deterministic
* int f() {
* try {
* int b = 0;
* int a = 1/b;
* } catch (Throwable t) {
* return t.hashCode();
* }
* return 0;
* }
*
*
*
* A constructor can be {@code @Pure}, but a constructor invocation 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.
*
* 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.
*
*
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.
*
*
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.
*
*
*
* @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 {}