Class ReturnRetention

java.lang.Object
org.ek9lang.compiler.support.ReturnRetention

public final class ReturnRetention extends Object
THE reading of what a call's RESULT may share with what it was called on - the return half of the CommonValues.RETAINS declaration. Use this wherever a check must know whether the value a call hands back can be a view of something else; never parse the RETAINS text again.

The built-ins DECLARE it (@Ek9Retains, stamped at bootstrap by OperationFactory); phase 5 DERIVES the same marker, with the same meaning, for a user method or operator that returns one of its own properties or a view of one (phase5/ReceiverInteriorReturns), so built-ins and user code follow one rule. The derived value is RECEIVER_INTERIOR, exactly the text a built-in declares.

A result MAY ALIAS when its callee declares any of:

  • return <- receiver-interior - a view of the receiver (JSON.get, DictEntry.value, Iterator.next);
  • return <- <parameter> - possibly an argument itself (List.getOrDefault's return <- defaultValue; a user function or method that returns a parameter, DERIVED by phase 5 in phase5/ReceiverInteriorReturns);
  • unknown - the inexpressible-retention opt-out, so nothing may be assumed.

It also answers the ARGUMENT half a caller needs: whether the callee may keep one of its arguments (retainsArgument(ScopedSymbol, int), e.g. List.+='s receiver <- item). Every rule is read through RetentionRule, which names a parameter by its declared EK9 name - so the rules are matched by FORM, never by a literal parameter name.

A member of a parameterised type is a substituted copy that may have been made before phase 5 derived the marker, so the generic's own member is read too (GenericTemplateMember); likewise a parameterised generic FUNCTION reads the generic function's own marker.

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final String
    The RETAINS rule saying a call's result is (part of) the object it was called on.
    static final String
    The DESTINATION of the keep rule of an abstract declaration nothing implements (unimplemented <- item): which implementation will run cannot be known, so it MAY keep the argument - never DEFINITELY (D80 item 3, Steve 2026-10-26).
  • Method Summary

    Modifier and Type
    Method
    Description
    calleeOf(EK9Parser.ExpressionContext expression, Function<org.antlr.v4.runtime.tree.ParseTree, ISymbol> recorded)
    The method, operator or function an expression CALLS when the whole expression is that call - a.get(k), first(), a + b, (a.get(k)) - so its value is whatever the call handed back.
    calleeOf(ISymbol recorded)
    The method or function a recorded symbol CALLS, when it is a call that hands back a value made elsewhere: a method, operator or function call - never a constructor, whose result is always fresh.
    static boolean
    definitelyKeepsArgument(ScopedSymbol callee, int parameterIndex)
    Does callee say, by an EXPLICIT rule - declared by a built-in or derived for a user callable - that it keeps the argument it is given at parameterIndex somewhere other than its result? The narrower question than keepsArgumentBeyondResult(ScopedSymbol, int), which also counts the inexpressible unknown opt-out: an unnamed closeable given to a callee that DEFINITELY keeps it is E81072; one given to a callee that may is handed on.
    static boolean
    Does callee say, by an EXPLICIT rule - declared by a built-in (readyHandler <- receiver) or derived for a user method - that it keeps the object it is called ON beyond the call: stores it in an argument or where nothing here can name it? The receiver's half of definitelyKeepsArgument(ScopedSymbol, int): an unnamed closeable that is the RECEIVER of such a call is E81072 (D80 follow-up, 2026-10-21: Tracked("r").registerIn(kept), whose body is items += this, closed the receiver and then the list held a closed object).
    static boolean
    handsBackArgument(ScopedSymbol callee, int parameterIndex)
    May the call hand the argument it is given at parameterIndex back as (part of) its result - return <- <that parameter>? The narrower question than retainsArgument(ScopedSymbol, int), which also counts an argument kept anywhere else (receiver <- item) and the unknown opt-out: the closeable ownership decision reports a hand-back (E81072) and treats any other keeping as handed on.
    static boolean
    Was the callee's retention DERIVED by phase 5 (a user callable) rather than DECLARED (a built-in's @Ek9Retains)? The closeable ownership decision treats the two differently: a derived link is honoured only where the return type may hold a borrowed view (BorrowedViewReturn).
    static boolean
    keepsArgumentBeyondResult(ScopedSymbol callee, int parameterIndex)
    May callee keep the argument it is given at parameterIndex somewhere other than its result - into its receiver, another argument, or anywhere (receiver <- item, unknown)? The question a constructor passing its own parameter on asks to know whether the parameter outlives the construction.
    static boolean
    May callee keep its receiver beyond the call - an explicit rule, or the unknown opt-out?
    static void
    markKeepsParameter(ScopedSymbol callable, String destination, String parameterName)
    Record, on a user method, operator or function, that the argument given for parameterName may be kept beyond the call - <destination> <- parameterName, exactly the text a built-in declares: the destination is receiver (stored in a property of the object), another parameter's name (added to the object that argument refers to) or ambient (held where nothing here can name it: a capture, a returned closure, a call that keeps it).
    static void
    markKeepsReceiver(ScopedSymbol callable, String destination)
    Record, on a user method or operator, that the object it is called on may be kept beyond the call - <destination> <- receiver, exactly the text a built-in declares (HTTP.whenReady's readyHandler <- receiver): the destination is another parameter's name (the receiver is stored in what that argument refers to) or ambient (held where nothing here can name it: a capture, a returned closure, a call that keeps it).
    static void
    Record that an abstract declaration nothing implements MAY keep each of its arguments (unimplemented <- <parameter>, UNIMPLEMENTED); the keep counterpart of markReturnsEachParameter(ScopedSymbol).
    static boolean
    markOverriddenBy(ScopedSymbol declaration, ScopedSymbol override)
    THE dispatch union (Steve, 2026-10-21, D61): a call through declaration may run override - a method that overrides it, or a function (dynamic functions included) whose super function it is - so the declaration also returns whatever the override does, and keeps whatever the override keeps (the lane callee-keep, 2026-10-21: receiver <- item, <otherParam> <- item, ambient <- item).
    static void
    An abstract declaration no program code implements: which implementation runs cannot be known, so its result may be any of its arguments - return <- <each parameter>.
    static void
    markReturnsParameter(ScopedSymbol callable, String parameterName)
    Record, on a user method, operator or function, that what it returns may be the argument given for the parameter parameterName - return <- parameterName, exactly the text a built-in declares (List.getOrDefault's return <- defaultValue).
    static void
    Record, on a user method or operator, that what it returns is (part of) its receiver.
    static boolean
    Does what callee returns possibly share an object with its receiver or an argument.
    static boolean
    mayKeepArgument(ScopedSymbol callee, int parameterIndex)
    The MAY half of definitelyKeepsArgument(ScopedSymbol, int): does callee say, by an EXPLICIT rule, that it keeps the argument - or is it an abstract declaration nothing implements, which MAY keep any argument (UNIMPLEMENTED)? An unnamed closeable given to such a callee is E81072 (nothing could close it); a named try resource given to it is allowed.
    static int
    parameterIndex(ScopedSymbol callee, String parameterName)
    The index of the parameter parameterName of callee; -1 when it declares none of that name.
    static List<ISymbol>
    The declared parameters of a method, operator or function; none for anything else.
    static List<String>
    The parameters callee stores its receiver INTO by an explicit rule (items <- receiver, declared or derived): the names of the arguments that end up holding the object it is called on.
    static boolean
    retainsArgument(ScopedSymbol callee, int parameterIndex)
    May callee keep (a reference to) the argument it is given at parameterIndex - into its receiver, another argument, its result or anywhere else (receiver <- item, return <- other, or unknown)? An argument the callee keeps is no longer the caller's alone.
    static List<org.ek9lang.tooling.construct.RetentionRule>
    THE rules saying what callee RETURNS (every return <- source it declares or has derived, the generic's own for a parameterisation or a member of one) - for a caller that must map each source back onto the receiver or the argument it names (phase5/ReturnSourceKind.origins).
    static boolean
    Does what callee returns possibly share an object with its RECEIVER.

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • RECEIVER_INTERIOR

      public static final String RECEIVER_INTERIOR
      The RETAINS rule saying a call's result is (part of) the object it was called on.
      See Also:
    • UNIMPLEMENTED

      public static final String UNIMPLEMENTED
      The DESTINATION of the keep rule of an abstract declaration nothing implements (unimplemented <- item): which implementation will run cannot be known, so it MAY keep the argument - never DEFINITELY (D80 item 3, Steve 2026-10-26). mayKeepArgument(ScopedSymbol, int) counts it, definitelyKeepsArgument(ScopedSymbol, int) does not, so an unnamed closeable given to it is E81072 (may-keep suffices: nothing could close it) while a named try resource is allowed (E81075 needs a callee that definitely keeps it). Once an implementation exists the rule is not written, and the union over every override (D61) decides.
      See Also:
  • Method Details

    • calleeOf

      public static Optional<ScopedSymbol> calleeOf(ISymbol recorded)
      The method or function a recorded symbol CALLS, when it is a call that hands back a value made elsewhere: a method, operator or function call - never a constructor, whose result is always fresh.
    • calleeOf

      public static Optional<ScopedSymbol> calleeOf(EK9Parser.ExpressionContext expression, Function<org.antlr.v4.runtime.tree.ParseTree, ISymbol> recorded)
      The method, operator or function an expression CALLS when the whole expression is that call - a.get(k), first(), a + b, (a.get(k)) - so its value is whatever the call handed back. Empty for a literal, an identifier, a constructor, a dynamic function, a list or dict literal and the control forms.
      Parameters:
      expression - the expression, as the compiler parsed it
      recorded - the recorded-symbol lookup of the phase asking (symbolsAndScopes or parsedModule)
    • mayAlias

      public static boolean mayAlias(ScopedSymbol callee)
      Does what callee returns possibly share an object with its receiver or an argument.
    • returnsReceiverInterior

      public static boolean returnsReceiverInterior(ScopedSymbol callee)
      Does what callee returns possibly share an object with its RECEIVER.
    • retainsArgument

      public static boolean retainsArgument(ScopedSymbol callee, int parameterIndex)
      May callee keep (a reference to) the argument it is given at parameterIndex - into its receiver, another argument, its result or anywhere else (receiver <- item, return <- other, or unknown)? An argument the callee keeps is no longer the caller's alone.
    • returnRules

      public static List<org.ek9lang.tooling.construct.RetentionRule> returnRules(ScopedSymbol callee)
      THE rules saying what callee RETURNS (every return <- source it declares or has derived, the generic's own for a parameterisation or a member of one) - for a caller that must map each source back onto the receiver or the argument it names (phase5/ReturnSourceKind.origins). The unknown opt-out has no rule to map, so it contributes none.
    • parameterIndex

      public static int parameterIndex(ScopedSymbol callee, String parameterName)
      The index of the parameter parameterName of callee; -1 when it declares none of that name.
    • parametersOf

      public static List<ISymbol> parametersOf(ScopedSymbol callee)
      The declared parameters of a method, operator or function; none for anything else.
    • isDerived

      public static boolean isDerived(ScopedSymbol callee)
      Was the callee's retention DERIVED by phase 5 (a user callable) rather than DECLARED (a built-in's @Ek9Retains)? The closeable ownership decision treats the two differently: a derived link is honoured only where the return type may hold a borrowed view (BorrowedViewReturn).
    • markReturnsReceiverInterior

      public static void markReturnsReceiverInterior(MethodSymbol method)
      Record, on a user method or operator, that what it returns is (part of) its receiver.
    • markReturnsParameter

      public static void markReturnsParameter(ScopedSymbol callable, String parameterName)
      Record, on a user method, operator or function, that what it returns may be the argument given for the parameter parameterName - return <- parameterName, exactly the text a built-in declares (List.getOrDefault's return <- defaultValue).
    • markOverriddenBy

      public static boolean markOverriddenBy(ScopedSymbol declaration, ScopedSymbol override)
      THE dispatch union (Steve, 2026-10-21, D61): a call through declaration may run override - a method that overrides it, or a function (dynamic functions included) whose super function it is - so the declaration also returns whatever the override does, and keeps whatever the override keeps (the lane callee-keep, 2026-10-21: receiver <- item, <otherParam> <- item, ambient <- item). Every rule of the override is recorded on the declaration, a parameter named by the declaration's own parameter at the same position. Marks only add.
      Returns:
      true when the declaration gained a rule
    • markReturnsEachParameter

      public static void markReturnsEachParameter(ScopedSymbol callable)
      An abstract declaration no program code implements: which implementation runs cannot be known, so its result may be any of its arguments - return <- <each parameter>.
    • handsBackArgument

      public static boolean handsBackArgument(ScopedSymbol callee, int parameterIndex)
      May the call hand the argument it is given at parameterIndex back as (part of) its result - return <- <that parameter>? The narrower question than retainsArgument(ScopedSymbol, int), which also counts an argument kept anywhere else (receiver <- item) and the unknown opt-out: the closeable ownership decision reports a hand-back (E81072) and treats any other keeping as handed on.
    • keepsArgumentBeyondResult

      public static boolean keepsArgumentBeyondResult(ScopedSymbol callee, int parameterIndex)
      May callee keep the argument it is given at parameterIndex somewhere other than its result - into its receiver, another argument, or anywhere (receiver <- item, unknown)? The question a constructor passing its own parameter on asks to know whether the parameter outlives the construction.
    • markKeepsParameter

      public static void markKeepsParameter(ScopedSymbol callable, String destination, String parameterName)
      Record, on a user method, operator or function, that the argument given for parameterName may be kept beyond the call - <destination> <- parameterName, exactly the text a built-in declares: the destination is receiver (stored in a property of the object), another parameter's name (added to the object that argument refers to) or ambient (held where nothing here can name it: a capture, a returned closure, a call that keeps it). Derived by phase5/CloseableArgumentKeeping, read by keepsArgumentBeyondResult(ScopedSymbol, int) and definitelyKeepsArgument(ScopedSymbol, int).
    • definitelyKeepsArgument

      public static boolean definitelyKeepsArgument(ScopedSymbol callee, int parameterIndex)
      Does callee say, by an EXPLICIT rule - declared by a built-in or derived for a user callable - that it keeps the argument it is given at parameterIndex somewhere other than its result? The narrower question than keepsArgumentBeyondResult(ScopedSymbol, int), which also counts the inexpressible unknown opt-out: an unnamed closeable given to a callee that DEFINITELY keeps it is E81072; one given to a callee that may is handed on.
    • mayKeepArgument

      public static boolean mayKeepArgument(ScopedSymbol callee, int parameterIndex)
      The MAY half of definitelyKeepsArgument(ScopedSymbol, int): does callee say, by an EXPLICIT rule, that it keeps the argument - or is it an abstract declaration nothing implements, which MAY keep any argument (UNIMPLEMENTED)? An unnamed closeable given to such a callee is E81072 (nothing could close it); a named try resource given to it is allowed. Still narrower than keepsArgumentBeyondResult(ScopedSymbol, int): the inexpressible unknown opt-out does not answer here.
    • markMayKeepEachParameter

      public static void markMayKeepEachParameter(ScopedSymbol callable)
      Record that an abstract declaration nothing implements MAY keep each of its arguments (unimplemented <- <parameter>, UNIMPLEMENTED); the keep counterpart of markReturnsEachParameter(ScopedSymbol).
    • definitelyKeepsReceiver

      public static boolean definitelyKeepsReceiver(ScopedSymbol callee)
      Does callee say, by an EXPLICIT rule - declared by a built-in (readyHandler <- receiver) or derived for a user method - that it keeps the object it is called ON beyond the call: stores it in an argument or where nothing here can name it? The receiver's half of definitelyKeepsArgument(ScopedSymbol, int): an unnamed closeable that is the RECEIVER of such a call is E81072 (D80 follow-up, 2026-10-21: Tracked("r").registerIn(kept), whose body is items += this, closed the receiver and then the list held a closed object). The unknown opt-out is not enough: the receiver is then only handed on. A rule storing the receiver in its own property (receiver <- receiver) is not a keep, and the receiver handed back is returnsReceiverInterior(ScopedSymbol).
    • receiverKeptInto

      public static List<String> receiverKeptInto(ScopedSymbol callee)
      The parameters callee stores its receiver INTO by an explicit rule (items <- receiver, declared or derived): the names of the arguments that end up holding the object it is called on. The ambient destination (held where nothing can name it) names no argument and is not listed. A try resource that is the receiver of such a call is asked where that argument was declared (E81075, matrix G14).
    • keepsReceiverBeyondResult

      public static boolean keepsReceiverBeyondResult(ScopedSymbol callee)
      May callee keep its receiver beyond the call - an explicit rule, or the unknown opt-out?
    • markKeepsReceiver

      public static void markKeepsReceiver(ScopedSymbol callable, String destination)
      Record, on a user method or operator, that the object it is called on may be kept beyond the call - <destination> <- receiver, exactly the text a built-in declares (HTTP.whenReady's readyHandler <- receiver): the destination is another parameter's name (the receiver is stored in what that argument refers to) or ambient (held where nothing here can name it: a capture, a returned closure, a call that keeps it). Derived by phase5/CloseableArgumentKeeping.