Issue: DEFMETHOD-DECLARATION-SCOPEReferences: DEFMETHOD, GENERIC-FUNCTION, GENERIC-FLET, GENERIC-LABELS,
CALL-NEXT-METHOD, NEXT-METHOD-P
Related issues: DECLARATION-SCOPE
LEXICAL-CONSTRUCT-GLOBAL-DEFINITION
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
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 (...)
... (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 (...)
...
...)))
...))
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.