CLHS: Issue DEFMETHOD-DECLARATION-SCOPE Writeup

#

## Issue DEFMETHOD-DECLARATION-SCOPE Writeup

    Issue:             DEFMETHOD-DECLARATION-SCOPE
    References:        DEFMETHOD, GENERIC-FUNCTION, GENERIC-FLET, GENERIC-LABELS,
                       CALL-NEXT-METHOD, NEXT-METHOD-P
    Related issues:    DECLARATION-SCOPE
                       ARGUMENT-MISMATCH-ERROR
                       LEXICAL-CONSTRUCT-GLOBAL-DEFINITION
                       METHOD-INITFORM
    Category:          CLARIFICATION
    Edit history:      v1, 27 Feb 91, Sandra Loosemore
                       v2, 28 Feb 91, Sandra Loosemore

    Problem description:

      The body of method definition in a DEFMETHOD, GENERIC-FUNCTION,
      GENERIC-FLET, or GENERIC-LABELS form includes an implicit FLET of
      CALL-NEXT-METHOD and NEXT-METHOD-P.  Can one put declarations at the
      head of the method body which apply to these bindings?  Do "free"
      declarations (or declarations that don't apply to bindings) at the
      head of the method body apply to the definitions of these local
      functions?

    Proposal (DEFMETHOD-DECLARATION-SCOPE:CORRESPONDS-TO-BINDINGS):

      Clarify that:

      (1) Declarations at the head of the method body that apply to the
          method's lambda variables are treated as "bound" declarations
          whose scope is the same as the corresponding bindings.

      (2) Declarations at the head of the method body that apply to the
          functional bindings of CALL-NEXT-METHOD or NEXT-METHOD-P apply
          to references to those functions within the method body forms.
          Any outer bindings of these functions and declarations associated
          with those bindings are shadowed within the method body forms.

      (3) The scope of "free" declarations at the head of the method body
          is the entire method body (including any implicit local function
          definitions), but excluding initialization forms for the lambda
          variables.

    Rationale:

      Items (1) and (3) are consistent with the rules from issue
      DECLARATION-SCOPE.

      For item (2), it would be counterintuitive if declarations for
      CALL-NEXT-METHOD or NEXT-METHOD-P that appeared at the head of
      a method body didn't actually apply to references within the body.

    Examples:

      (1) Must the call to CALL-NEXT-METHOD be NOTINLINE?

          (defmethod baz (...)
            (declare (notinline call-next-method))
            ... (call-next-method))

          Under proposal CORRESPONDS-TO-BINDINGS, the answer is that the
          declaration does apply.  The NOTINLINE declaration applies to
          the local binding of CALL-NEXT-METHOD established within the
          method definition, not to some outer binding that is shadowed by
          the local binding.

      (2) Is the definition of CALL-NEXT-METHOD "safe"?  (See issue
          ARGUMENT-MISMATCH-ERROR for why it might matter.)

          (defmethod baz (...)
            (declare (optimize safety))
            ... (call-next-method))

          Under proposal CORRESPONDS-TO-BINDINGS, the answer is yes.  The
          definition of CALL-NEXT-METHOD is in the scope of the declaration.

      (3) Must the call to CALL-NEXT-METHOD be NOTINLINE?

          (defmethod foo (...)
            (declare (notinline call-next-method))
            (generic-flet ((bar (...)
        		         (:method (...)
    		            ...
    		            (call-next-method)
    		            ...)))
              ...))

          Under proposal CORRESPONDS-TO-BINDINGS, the answer is no.  The
          NOTINLINE declaration is shadowed by the rebinding of
          CALL-NEXT-METHOD within the nested method definition.

    Current Practice:

      Chestnut's Lisp-to-C translator conforms to this proposal.

      It appears that PCL puts all the declarations at the head of the
      method body at the head of the resulting lambda-expression, where
      they can be shadowed by the FLET.

      Lucid 4.0 appears to scope "bound" declarations in accordance with
      this proposal, but not "free" declarations.

    Cost to Implementors:

      Probably small.  Note, however, that it is necessary for DEFMETHOD
      and GENERIC-FUNCTION to (internally) use something like PARSE-DECLARATIONS
      to compute their macro expansions, in order to sort out which declarations
      apply to which binding form.  Presumably many implementations have
      something like that anyway, but the other cases where it's needed (LET*,
      (LAMBDA ...), LABELS, GENERIC-LABELS) are all special forms and not
      macros.

    Cost to Users:

      Probably small.

    Cost of non-adoption:

      Continuing vagueness in the language specification.

    Performance impact:

      Probably small.

    Benefits:

      The cost of non-adoption is avoided.

    Esthetics:

      See the "rationale".

    Discussion:

      The specification of DEFMETHOD and the other method-defining forms
      doesn't really state explicitly that CALL-NEXT-METHOD and NEXT-METHOD-P
      are required to be locally rebound within method definitions that
      reference them.  (Document 88-002R says they have "lexical scope and
      indefinite extent".)  However, it's necessary to make this point
      explicit so that the behavior of test case (3) is well-defined.

      It is assumed to be unambiguous that "bound" declarations that apply
      to the method's lambda variables can appear at the head of the method
      body, and that the scope of the declarations is the same as the scope
      of the variable bindings, although 88-002R doesn't say that explicitly
      either.

Copyright 1996-2005, LispWorks Ltd. All rights reserved.