--- /dev/null
+@node Deprecated Interfaces
+@comment node-name, next, previous, up
+@chapter Deprecated Interfaces
+
+This chapter documents the deprecation process used for SBCL
+interfaces, and lists legacy interfaces in various stages of
+deprecation.
+
+This should not be confused with those things the ANSI Common Lisp
+standard calls ``deprecated'': the entirety of ANCL CL is supported by
+SBCL, and none of those interfaces are subject to censure.
+
+@section Why Deprecate?
+
+While generally speaking we try to keep SBCL changes as backwards
+compatible as feasible, there are situations when existing interfaces
+are deprecated:
+
+@itemize
+
+@item @strong{Broken Interfaces}
+
+Sometimes it turns out that an interface is sufficiently misdesigned
+that fixing it would be worse than deprecating it and replacing it
+with another.
+
+This is typically the case when fixing the interface would change its
+semantics in ways that could break user code subtly: in such cases we
+may end up considering the obvious breakage caused by deprecation to
+be preferable.
+
+Another example are functions or macros whose current signature makes
+them hard or impossible to extend in the future: backwards compatible
+extensions would either make the interface intolerably hairy, or are
+sometimes outright impossible.
+
+@item @strong{Internal Interfaces}
+
+SBCL has several internal interfaces that were never meant to be used
+in user code -- or at least never meant to be used in user code
+unwilling to track changes to SBCL internals.
+
+Ideally we'd like to be free to refactor our own internals as we
+please, without even going through the hassle of deprecating things.
+Sometimes, however, it turns out that our internal interfaces have
+several external users who aren't using them advicedly, but due to
+misunderstandings regarding their status or stability.
+
+Consider a deprecated internal interface a reminder for SBCL
+maintainers not to delete the thing just yet, even though it is seems
+unused -- because it has external users.
+
+When internal interfaces are deprecated we try our best to provide
+supported alternatives.
+
+@item @strong{Aesthetics & Ease of Maintenance}
+
+Sometimes an interface isn't broken or internal, but just inconsistent
+somehow.
+
+This mostly happens only with historical interfaces inherited from
+CMUCL which often haven't been officially supported in SBCL before, or
+with new extensions to SBCL that haven't been around for very long in
+the first place.
+
+The alternative would be to keep the suboptimal version around
+forever, possibly alongside an improved version. Sometimes we may do
+just that, but because every line of code comes with a maintenance
+cost, sometimes we opt to deprecate the suboptimal version instead:
+SBCL doesn't have infinite developer resources.
+
+We also believe that sometimes cleaning out legacy interfaces helps
+keep the whole system more comprehensible to users, and makes
+introspective tools such as @code{apropos} more useful.
+
+@end itemize
+
+@section What Happens During Deprecation?
+
+Deprecation proceeds in three stages, each lasting approximately a
+year. In some cases it migh move slower or faster, but year per stage
+is what we aim at in general.
+
+During each stage warnings (and errors) of increasing severity are
+signaled, which note that the interface is deprecated, and point users
+towards any replacements when applicable.
+
+@enumerate
+
+@item @strong{Early Deprecation}
+
+During early deprecation the interface is kept in working condition,
+but a style-warning will be signalled for uses of it at compile-time.
+
+The internals may change at this stage: typically because the interface
+is re-implemented on top of its successor. While we try to keep things
+as backwards-compatible as feasible (taking maintenance costs into account),
+sometimes semantics change slightly.
+
+For example, when spinlock API was deprecated, spinlock objects ceased
+to exist, and the whole spinlock API became a synonym for the mutex
+API -- so code using the spinlock API continued working, but silently
+switched to mutexes instead. However, if someone relied on
+
+ @code{(typep lock 'spinlock)}
+
+returning @code{NIL} for a mutexes, trouble could ensue.
+
+@item @strong{Late Deprecation}
+
+During late deprecation the interface remains as it was during early
+deprecation, but the compile-time warning is upgraded to a full
+warning.
+
+@item @strong{Final Deprecation}
+
+During final deprecation the symbols still exist, but using the
+interface will cause not only the compile-time full warning, but also
+a runtime error.
+
+@end enumerate
+
+After final deprecation the interface is deleted entirely.
+
+@section List of Deprecated Interfaces
+
+@subsection Early Deprecation
+
+@itemize
+
+@item @strong{SB-EXT:QUIT}
+
+Deprecated in favor of @code{sb-ext:exit} as of 1.0.56.55 in May 2012.
+Expected to move into late deprecation in May 2013.
+
+The design of @code{sb-ext:quit} proved too broken to fix in a
+backwards-compatible manner, so it had to be deprecated and replaced.
+
+Problems with it were manifold: when called in the main thread it
+cause the entire process to exit. When called in another thread with
+@code{:recklessly-p} it also caused the entire process to exit.
+However, when called in another thread without @code{:recklessly-p} it
+instead caused that thread to terminate abnormally without terminating
+the process. Its behaviour versus other threads than the one it was
+called in was also underspecified, and dependent on things such as the
+current session. Any conceivable change that would have made it sane
+would also have silently broken code that depended on the old
+behaviour.
+
+@strong{Remedy}
+
+For code needing to work with legacy SBCLs, if you were calling
+@code{quit} with @code{:recklessly-p t}, use
+
+@sp 1
+@lisp
+(defun system-exit (&optional (code 0))
+ (alien-funcall (extern-alien "exit" (function void int)) code))
+@end lisp
+@sp 1
+
+instead. In modern SBCLs simply call either @code{sb-posix:exit} or
+@code{sb-ext:exit}.
+
+If you were calling it without @code{:recklessly-p}, be advised
+that your code may not function as expected when called from threads
+other than the main one (see above) -- in any case, you can support
+legacy SBCLs using the following conditionalization:
+
+@sp 1
+@lisp
+(defun lisp-exit (&key (code 0) abort)
+ #+#.(cl:if (cl:find-symbol "EXIT" :sb-ext) '(and) '(or))
+ ;; Assuming process exit is what is desired -- if thread termination
+ ;; is intended, use SB-THREAD:ABORT-THREAD instead.
+ (sb-ext:exit :code code :abort abort)
+ #-#.(cl:if (cl:find-symbol "EXIT" :sb-ext) '(and) '(or))
+ (sb-ext:quit :unix-status code :recklessly-p abort))
+@end lisp
+@sp 1
+
+@sp 1
+@item @strong{SB-UNIX:UNIX-EXIT}
+
+Deprecated as of 1.0.56.55 in May 2012. Expected to move into late
+deprecation in May 2013.
+
+When the SBCL process termination was refactored as part of changes that
+led to @code{sb-ext:quit} being deprecated, @code{sb-unix:unix-exit}
+ceased to be used internally. Since @code{SB-UNIX} is an internal package
+not intended for user code to use, and since we're slowly in the process
+of refactoring things to be less Unix-oriented, @code{sb-unix:unix-exit}
+was initially deleted as it was no longer used. Unfortuntely it became
+apparent that it was used by several external users, so it was re-instated
+in deprecated form.
+
+While the cost of keeping @code{sb-unix:unix-exit} indefinitely is
+trivial, the ability to refactor our internals is important, so its
+deprecation was taken as an opportunity to highlight that
+@code{SB-UNIX} is an internal package and @code{SB-POSIX} should be
+used by user-programs instead -- or alternatively calling the foreign
+function directly if the desired interface doesn't for some reason
+exist in @code{SB-POSIX}.
+
+@strong{Remedy}
+
+For code needing to work with legacy SBCLs, use eg. @code{system-exit}
+as show above in remedies for @code{sb-ext:quit}. In modern SBCLs
+simply call either @code{sb-posix:exit} or @code{sb-ext:exit} with
+appropriate arguments.
+
+@sp 1
+@item @strong{SB-C::MERGE-TAIL-CALLS Compiler Policy}
+
+Deprecated as of 1.0.53.74 in November 2011. Expected to move into
+late deprecation in November 2012.
+
+This compiler policy was never functional: SBCL has always merged tail
+calls when it could, regardless of this policy setting. (It was also
+never officially supported, but several code-bases have historically
+used it.)
+
+@strong{Remedy}
+
+Simply remove the policy declarations. They were never necessary: SBCL
+always merged tail-calls when possible. To disable tail merging,
+structure the code to avoid the tail position instead.
+
+@sp 1
+@item @strong{Spinlock API}
+
+Deprecated as of 1.0.53.11 in August 2011. Expected to move into late
+deprecation in August 2012.
+
+Spinlocks were an internal interface, but had a number of external users
+and were hence deprecated instead of being simply deleted.
+
+Affected symbols: @code{sb-thread::spinlock},
+@code{sb-thread::make-spinlock}, @code{sb-thread::with-spinlock},
+@code{sb-thread::with-recursive-spinlock},
+@code{sb-thread::get-spinlock}, @code{sb-thread::release-spinlock},
+@code{sb-thread::spinlock-value}, and @code{sb-thread::spinlock-name}.
+
+@strong{Remedy}
+
+Use the mutex API instead, or implement spinlocks suiting your needs
+on top of @code{sb-ext:compare-and-swap},
+@code{sb-ext:spin-loop-hint}, etc.
+
+@end itemize
+
+@subsection Late Deprecation
+
+@itemize
+
+@item @strong{SB-THREAD:JOIN-THREAD-ERROR-THREAD and SB-THREAD:INTERRUPT-THREAD-ERROR-THREAD}
+
+Deprecated in favor of @code{sb-thread:thread-error-thread} as of
+1.0.29.17 in June 2009. Expected to move into final deprecation in
+June 2012.
+
+@strong{Remedy}
+
+For code that needs to support legacy SBCLs, use eg.:
+
+@sp 1
+@lisp
+(defun get-thread-error-thread (condition)
+ #+#.(cl:if (cl:find-symbol "THREAD-ERROR-THREAD" :sb-thread)
+ '(and) '(or))
+ (sb-thread:thread-error-thread condition)
+ #-#.(cl:if (cl:find-symbol "THREAD-ERROR-THREAD" :sb-thread)
+ '(and) '(or))
+ (etypecase condition
+ (sb-thread:join-thread-error
+ (sb-thread:join-thread-error-thread condition))
+ (sb-thread:interrupt-thread-error
+ (sb-thread:interrupt-thread-error-thread condition))))
+@end lisp
+@sp 1
+
+@sp 1
+@item @strong{SB-INTROSPECT:FUNCTION-ARGLIST}
+
+Deprecated in favor of @code{sb-introspect:function-lambda-list} as of
+1.0.24.5 in January 2009. Expected to move into final deprecation in
+January 2012.
+
+Renamed for consistency and aesthetics. Functions have lambda-lists,
+not arglists.
+
+@strong{Remedy}
+
+For code that needs to support legacy SBCLs, use eg.:
+
+@sp 1
+@lisp
+(defun get-function-lambda-list (function)
+ #+#.(cl:if (cl:find-symbol "FUNCTION-LAMBDA-LIST" :sb-introspect)
+ '(and) '(or))
+ (sb-introspect:function-lambda-list function)
+ #-#.(cl:if (cl:find-symbol "FUNCTION-LAMBDA-LIST" :sb-introspect)
+ '(and) '(or))
+ (sb-introspect:function-arglist function))
+@end lisp
+@sp 1
+
+@sp 1
+@item @strong{Stack Allocation Policies}
+
+Deprecated in favor of @code{sb-ext:*stack-allocate-dynamic-extent*}
+as of 1.0.19.7 in August 2008, and are expected to be removed in
+August 2012.
+
+Affected symbols: @code{sb-c::stack-allocate-dynamic-extent},
+@code{sb-c::stack-allocate-vector}, and
+@code{sb-c::stack-allocate-value-cells}.
+
+These compiler policies were never officially supported, and turned
+out the be a flawed design.
+
+@strong{Remedy}
+
+For code that needs stack-allocation in legacy SBCLs, conditionalize
+using:
+
+@sp 1
+@lisp
+#-#.(cl:if (cl:find-symbol "*STACK-ALLOCATE-DYNAMIC-EXTENT*" :sb-ext)
+ '(and) '(or))
+(declare (optimize sb-c::stack-allocate-dynamic-extent))
+@end lisp
+@sp 1
+
+However, unless stack allocation is essential, we recommend simply
+removing these declarations. Refer to documentation on
+@code{sb-ext:*stack-allocate-dynamic*} for details on stack allocation
+control in modern SBCLs.
+
+@sp 1
+@item @strong{SB-SYS:OUTPUT-RAW-BYTES}
+
+Deprecated as of 1.0.8.16 in June 2007. Expected to move into final
+deprecation in June 2012.
+
+Internal interface with some external users. Never officially
+supported, deemed unnecessary in presence of @code{write-sequence} and
+bivalent streams.
+
+@strong{Remedy}
+
+Use streams with element-type @code{(unsigned-byte 8)}
+or @code{:default} -- the latter allowing both binary and
+character IO -- in conjunction with @code{write-sequence}.
+
+@end itemize
+
+@subsection Final Deprecation
+
+No interfaces are currently in final deprecation.
+
+@section Historical Interfaces
+
+The following is a partial list of interfaces present in historical
+versions of SBCL, which have since then been deleted.
+
+@itemize
+
+@item @strong{SB-KERNEL:INSTANCE-LAMBDA}
+
+Historically needed for CLOS code. Deprecated as of 0.9.3.32 in August
+2005. Deleted as of 1.0.47.8 in April 2011. Plain @code{lambda} can be
+used where @code{sb-kernel:instance-lambda} used to be needed.
+
+@sp 1
+@item @strong{SB-ALIEN:DEF-ALIEN-ROUTINE, SB-ALIEN:DEF-ALIEN-VARIABLE, SB-ALIEN:DEF-ALIEN-TYPE}
+
+Inherited from CMUCL, naming convention not consistent with preferred
+SBCL style. Deprecated as of 0.pre7.90 in December 2001. Deleted as of
+1.0.9.17 in September 2007. Replaced by
+@code{sb-alien:define-alien-routine},
+@code{sb-alien:define-alien-variable}, and
+@code{sb-alien:define-alien-type}.
+
+@end itemize