All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.checkerframework.dataflow.qual.Deterministic Maven / Gradle / Ivy

There is a newer version: 9.3.0
Show newest version
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: * *

    *
  1. Assignment to any expression, except for local variables and method parameters.
    * (Note that storing into an array element, such a {@code a[i] = x}, is not an assignment to * a variable and is therefore forbidden.) *
  2. A method invocation of a method that is not {@link Deterministic}. *
  3. Construction of a new object. *
  4. 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;
     * }
     * 
    *
* * When a constructor is annotated as {@code Deterministic} (or {@code @Pure}), that means that all * the fields are deterministic (the same values, if the arguments are the same). The constructed * object itself is different. That is, a constructor invocation is never deterministic * since it returns a different new object each time. * *

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. * *

This annotation is inherited by subtypes, just as if it were meta-annotated with * {@code @InheritedAnnotation}. * * @checker_framework.manual #type-refinement-purity Side effects, determinism, purity, and * flow-sensitive analysis */ // @InheritedAnnotation cannot be written here, because "dataflow" project cannot depend on // "framework" project. @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) public @interface Deterministic {}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy