From 11802a47e04b0dbfbfec03d8b438fb59f84ce35d Mon Sep 17 00:00:00 2001 From: Nikodemus Siivola Date: Wed, 2 May 2012 14:48:35 +0300 Subject: [PATCH] more deprecation * Add "Deprecated Interfaces" chapter to the manual. * Add list of deprecated interfaces along with a policy note to a comment near DEFINE-DEPRECATED-FUNCTION. * Add a proper deprecation warning for SB-C::MERGE-TAIL-CALLS. * Fix the deprecation warning for WITH-SPINLOCK. (Accidentally referred to WITH-RECURSIVE-SPINLOCK before.) --- doc/manual/deprecated.texinfo | 385 ++++++++++++++++++++++++++++++++++++++++ doc/manual/sbcl.texinfo | 2 + src/code/early-extensions.lisp | 39 ++++ src/code/thread.lisp | 2 +- src/compiler/policies.lisp | 4 - src/compiler/policy.lisp | 15 +- 6 files changed, 437 insertions(+), 10 deletions(-) create mode 100644 doc/manual/deprecated.texinfo diff --git a/doc/manual/deprecated.texinfo b/doc/manual/deprecated.texinfo new file mode 100644 index 0000000..97b0b13 --- /dev/null +++ b/doc/manual/deprecated.texinfo @@ -0,0 +1,385 @@ +@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 diff --git a/doc/manual/sbcl.texinfo b/doc/manual/sbcl.texinfo index e13c47f..6c316dc 100644 --- a/doc/manual/sbcl.texinfo +++ b/doc/manual/sbcl.texinfo @@ -91,6 +91,7 @@ provided with absolutely no warranty. See the @file{COPYING} and * Networking:: * Profiling:: * Contributed Modules:: +* Deprecated Interfaces:: * Concept Index:: * Function Index:: * Variable Index:: @@ -116,6 +117,7 @@ provided with absolutely no warranty. See the @file{COPYING} and @include sb-bsd-sockets/sb-bsd-sockets.texinfo @include profiling.texinfo @include contrib-modules.texinfo +@include deprecated.texinfo @include backmatter.texinfo @bye diff --git a/src/code/early-extensions.lisp b/src/code/early-extensions.lisp index 1d297c3..bde43c1 100644 --- a/src/code/early-extensions.lisp +++ b/src/code/early-extensions.lisp @@ -1123,6 +1123,45 @@ (deprecation-warning state since name replacements) form)) +;;; STATE is one of +;;; +;;; :EARLY, for a compile-time style-warning. +;;; :LATE, for a compile-time full warning. +;;; :FINAL, for a compile-time full warning and runtime error. +;;; +;;; Suggested duration of each stage is one year, but some things can move faster, +;;; and some widely used legacy APIs might need to move slower. Internals we don't +;;; usually add deprecation notes for, but sometimes an internal API actually has +;;; several external users, in which case we try to be nice about it. +;;; +;;; When you deprecate something, note it here till it is fully gone: makes it +;;; easier to keep things progressing orderly. Also add the relevant section +;;; (or update it when deprecation proceeds) in the manual, in +;;; deprecated.texinfo. +;;; +;;; EARLY: +;;; - SB-THREAD::SPINLOCK (type), since 1.0.53.11 (08/2011) -> Late: 08/2012 +;;; - SB-THREAD::MAKE-SPINLOCK, since 1.0.53.11 (08/2011) -> Late: 08/2012 +;;; - SB-THREAD::WITH-SPINLOCK, since 1.0.53.11 (08/2011) -> Late: 08/2012 +;;; - SB-THREAD::WITH-RECURSIVE-SPINLOCK, since 1.0.53.11 (08/2011) -> Late: 08/2012 +;;; - SB-THREAD::GET-SPINLOCK, since 1.0.53.11 (08/2011) -> Late: 08/2012 +;;; - SB-THREAD::RELEASE-SPINLOCK, since 1.0.53.11 (08/2011) -> Late: 08/2012 +;;; - SB-THREAD::SPINLOCK-VALUE, since 1.0.53.11 (08/2011) -> Late: 08/2012 +;;; - SB-THREAD::SPINLOCK-NAME, since 1.0.53.11 (08/2011) -> Late: 08/2012 +;;; - SETF SB-THREAD::SPINLOCK-NAME, since 1.0.53.11 (08/2011) -> Late: 08/2012 +;;; - SB-C::MERGE-TAIL-CALLS (policy), since 1.0.53.74 (11/2011) -> Late: 11/2012 +;;; - SB-EXT:QUIT, since 1.0.56.55 (05/2012) -> Late: 05/2013 +;;; - SB-UNIX:UNIX-EXIT, since 1.0.56.55 (05/2012) -> Late: 05/2013 +;;; +;;; LATE: +;;; - SB-SYS:OUTPUT-RAW-BYTES, since 1.0.8.16 (06/2007) -> Final: anytime +;;; - SB-C::STACK-ALLOCATE-DYNAMIC-EXTENT (policy), since 1.0.19.7 -> Final: anytime +;;; - SB-C::STACK-ALLOCATE-VECTOR (policy), since 1.0.19.7 -> Final: anytime +;;; - SB-C::STACK-ALLOCATE-VALUE-CELLS (policy), since 1.0.19.7 -> Final: anytime +;;; - SB-INTROSPECT:FUNCTION-ARGLIST, since 1.0.24.5 (01/2009) -> Final: anytime +;;; - SB-THREAD:JOIN-THREAD-ERROR-THREAD, since 1.0.29.17 (06/2009) -> Final: 09/2012 +;;; - SB-THREAD:INTERRUPT-THREAD-ERROR-THREAD since 1.0.29.17 (06/2009) -> Final: 06/2012 + (defmacro define-deprecated-function (state since name replacements lambda-list &body body) (let* ((replacements (normalize-deprecation-replacements replacements)) (doc (let ((*package* (find-package :keyword))) diff --git a/src/code/thread.lisp b/src/code/thread.lisp index 5188793..09c2cc4 100644 --- a/src/code/thread.lisp +++ b/src/code/thread.lisp @@ -94,7 +94,7 @@ stale value, use MUTEX-OWNER instead." ,@body)) (sb!xc:defmacro with-spinlock ((lock) &body body) - (deprecation-warning :early "1.0.53.11" 'with-recursive-spinlock 'with-mutex) + (deprecation-warning :early "1.0.53.11" 'with-spinlock 'with-mutex) `(with-mutex (,lock) ,@body)) diff --git a/src/compiler/policies.lisp b/src/compiler/policies.lisp index 53b21e4..3717744 100644 --- a/src/compiler/policies.lisp +++ b/src/compiler/policies.lisp @@ -61,10 +61,6 @@ more reliable bactracing across foreign calls.") (if (zerop safety) 0 3) ("no" "maybe" "yes" "yes")) -(define-optimization-quality merge-tail-calls - 3 - "Deprecated: has no effect on compiled code. (Never really did.)") - (define-optimization-quality insert-debug-catch (if (> debug (max speed space)) 3 diff --git a/src/compiler/policy.lisp b/src/compiler/policy.lisp index 413e425..c6b31aa 100644 --- a/src/compiler/policy.lisp +++ b/src/compiler/policy.lisp @@ -76,11 +76,16 @@ EXPERIMENTAL INTERFACE: Subject to change." ;;; Is it deprecated? (defun policy-quality-deprecation-warning (quality) - (when (member quality '(stack-allocate-dynamic-extent stack-allocate-vector - stack-allocate-value-cells)) - (deprecation-warning :late "1.0.19.7" quality '*stack-allocate-dynamic-extent* - :runtime-error nil) - t)) + (case quality + ((stack-allocate-dynamic-extent stack-allocate-vector stack-allocate-value-cells) + (deprecation-warning :late "1.0.19.7" quality '*stack-allocate-dynamic-extent* + :runtime-error nil) + t) + ((merge-tail-calls) + (deprecation-warning :early "1.0.53.74" quality nil :runtime-error nil) + t) + (otherwise + nil))) ;;; *POLICY* holds the current global compiler policy information, as ;;; an alist mapping from optimization quality name to quality value. -- 1.7.10.4