Annotation Type CreatesMustCallFor


  • @Target(METHOD)
    @InheritedAnnotation
    @Retention(RUNTIME)
    @Repeatable(List.class)
    public @interface CreatesMustCallFor
    Indicates that the method resets the expression's must-call type to its declared type. This effectively undoes flow-sensitive type refinement. The expression is the value argument/element. More precisely, a call to a method annotated by this annotation changes the expression's must-call type to the least upper bound of its current must-call type and its declared must-call type.

    When calling a method annotated as @CreatesMustCallFor("expression"), the expression's static type in the Called Methods type system must be @CalledMethods({}). That is, expression's CalledMethods type must be empty.

    @CreatesMustCallFor("obj") must be written on any method that assigns a non-final, owning field of obj whose declared type has a must-call obligation.

    Because this annotation can only add obligations, it can be written safely on any method, even one that does not actually create a new obligation. Writing this annotation on a method that does not actually create any new obligations may lead to false alarms (warnings at correct code), but never to missed alarms (lack of warnings at incorrect code).

    As an example, consider the following code, which uses a @CreatesMustCallFor annotation to indicate that the reset() method re-assigns the socket field:

     @MustCall("stop")
     class SocketContainer {
         // Note that @MustCall("close") is the default type for java.net.Socket, but it
         // is included on the next line for illustrative purposes. This example would function
         // identically if that qualifier were omitted.
         private @Owning @MustCall("close") Socket socket = ...;
    
         @EnsuresCalledMethods(value="this.socket", methods="close")
         public void stop() throws IOException {
           socket.close();
         }
    
        @CreatesMustCallFor("this")
        public void reset() {
          if (socket.isClosed()) {
            socket = new Socket(...);
          }
        }
     }
     
    A client of SocketContainer is permitted to call reset() arbitrarily many times. Each time it does so, a new Socket might be created. A SocketContainer's must-call obligation of "stop" is fulfilled only if stop() is called after the last call to reset(). The @CreatesMustCallFor annotation on reset()'s declaration enforces this requirement: at any call to reset(), all called-methods information about the receiver is removed from the store of the Must Call Checker and the store of the Called Methods Checker, so the client has to "start over" as if a fresh SocketContainer object had been created.

    When the -AnoCreatesMustCallFor command-line argument is passed to the checker, this annotation is ignored and all fields are treated as non-owning.

    See the Checker Framework Manual:
    Resource Leak Checker
    • Optional Element Summary

      Optional Elements 
      Modifier and Type Optional Element Description
      java.lang.String value
      Returns the expression whose must-call type is reset after a call to a method with this annotation.
    • Element Detail

      • value

        @JavaExpression
        java.lang.String value
        Returns the expression whose must-call type is reset after a call to a method with this annotation. The expression must be visible in the scope immediately before each call site, so it can only refer to fields, the method's parameters (which should be referenced via the "#X" syntax, where "#1" is the first argument, #2 is the second, etc.), or "this". The default is "this". At call-sites, the viewpoint-adapted referent of expression must be owning (an owning field, a local variable tracked in a resource alias set, etc.) or a reset.not.owning error is issued.
        Returns:
        the expression to which must-call obligations are added when the annotated method is invoked
        Default:
        "this"