From: Tobias C. R. <tc...@fr...> - 2009-04-22 15:38:10
|
It seems that only very simple types are derived for literal data. For example, the list literal '(1 2 3) will get the type CONS, although (CONS FIXNUM (CONS FIXNUM (CONS FIXNUM NULL))) would be more accurate. I can see that being a reasonable choice as otherwise program literals would turn into gigantic types. However, wouldn't it perhaps make sense to derive types for lists to the 5th, or perhaps 7th element? I'm currently trying myself to come up with a DEFTRANSFORM for SB-INT:PROPER-LIST-OF-LENGTH to make the compile-time checking of DESTRUCTURING-BIND a bit smarter. For example, if types for literal lists were derived, we'd catch (destructuring-bind (a b c d e f) '(1 2 3) ...) at compile-time. That's a stupid example, but think of an inlined function producing a list of fixed length. (For the latter to work, (DEFUN FOO () (LIST 1 2 3 4)) would have to get a more accurate type, too.) If you agree, could you please provide a hint how literal data get their types? I assume the case with LIST could be made work by an DEFTRANSFORM, couldn't it? -T. |
From: Nikodemus S. <nik...@ra...> - 2009-04-22 16:57:20
|
2009/4/22 Tobias C. Rittweiler <tc...@fr...>: > > It seems that only very simple types are derived for literal data. For > example, the list literal '(1 2 3) will get the type CONS, although > (CONS FIXNUM (CONS FIXNUM (CONS FIXNUM NULL))) would be more accurate. The reason why this is currently a bad idea is that type inference doesn't deal with compound types correctly: the inoccuous THE below makes SBCL think that X is still a (CONS FIXNUM FIXNUM) even after the SETF CAR. (defun foo (y) (declare (optimize safety)) (let ((x (the (cons fixnum fixnum) (cons 1 2)))) (setf (car x) y) (+ (car x) (cdr x)))) (foo "foo") ; => 74339983 Oops... Here's the bug: https://bugs.launchpad.net/sbcl/+bug/309445 Cheers, -- Nikodemus |
From: Nikodemus S. <nik...@ra...> - 2009-04-22 18:55:05
|
2009/4/22 Nikodemus Siivola <nik...@ra...>: > The reason why this is currently a bad idea is that type inference > doesn't deal with compound types correctly: the inoccuous THE below > makes SBCL think that X is still a (CONS FIXNUM FIXNUM) even after the > SETF CAR. > > (defun foo (y) > (declare (optimize safety)) > (let ((x (the (cons fixnum fixnum) (cons 1 2)))) > (setf (car x) y) > (+ (car x) (cdr x)))) > > (foo "foo") ; => 74339983 > > Oops... Here's the bug: > > https://bugs.launchpad.net/sbcl/+bug/309445 I did some more looking around this issue. One way to fix this would be to generate some sort of a dummy SET node for each function that messes up a compound object (%RPLACA, %RPLACD, destructive list functions, etc.) Seems like a principled way to fix this -- but requires making a comprehensive list of things which can mess things up. With the additional SET nodes -- and some additional magic -- PROPAGATE-FROM-SETS should be able to deal with this. Cheers, -- Nikodemus |
From: Nikodemus S. <nik...@ra...> - 2009-04-23 19:36:13
Attachments:
lvar-conservative-type.patch
|
2009/4/22 Nikodemus Siivola <nik...@ra...>: >> (defun foo (y) >> (declare (optimize safety)) >> (let ((x (the (cons fixnum fixnum) (cons 1 2)))) >> (setf (car x) y) >> (+ (car x) (cdr x)))) >> >> (foo "foo") ; => 74339983 >> >> Oops... Here's the bug: >> >> https://bugs.launchpad.net/sbcl/+bug/309445 > > I did some more looking around this issue. > > One way to fix this [snip] Another, much easier, way is sketched in the attached patch. Basically: CAR and CDR derive the type as T unless 1) there is only a single ref to the leaf in which case it cannot be mutated before CAR gets it 2) the type is actually declared. I still need to also make sure that PROPAGATE-TO-REFS cannot narrow the declared type down accidentally, eg. like when you insert (DECLARE (TYPE (CONS T FIXNUM) X) to the example above -- it doesn't happen there, but I'm not sure it cannot ever happen yet. Cheers, -- Nikodemus |
From: Nikodemus S. <nik...@ra...> - 2009-04-23 21:05:25
Attachments:
lvar-conservative-type-2.patch
|
2009/4/23 Nikodemus Siivola <nik...@ra...>: > Basically: CAR and CDR derive the type as T unless 1) there is only a > single ref to the leaf in which case it cannot be mutated before CAR > gets it 2) the type is actually declared. > > I still need to also make sure that PROPAGATE-TO-REFS cannot narrow > the declared type down accidentally, eg. like when you insert (DECLARE > (TYPE (CONS T FIXNUM) X) to the example above -- it doesn't happen > there, but I'm not sure it cannot ever happen yet. The answer is that it does. Attached patch is starting to look pretty good to my eyes, deals with results of ADJUST-ARRAY as well, and passes all my current test-cases. Anyone want to poke holes at it? Cheers. -- Nikodemus |
From: Tobias C. R. <tc...@fr...> - 2009-04-24 08:12:36
|
Nikodemus Siivola <nik...@ra...> writes: > 2009/4/23 Nikodemus Siivola <nik...@ra...>: > >> Basically: CAR and CDR derive the type as T unless 1) there is only a >> single ref to the leaf in which case it cannot be mutated before CAR >> gets it 2) the type is actually declared. >> >> I still need to also make sure that PROPAGATE-TO-REFS cannot narrow >> the declared type down accidentally, eg. like when you insert (DECLARE >> (TYPE (CONS T FIXNUM) X) to the example above -- it doesn't happen >> there, but I'm not sure it cannot ever happen yet. > > The answer is that it does. Attached patch is starting to look pretty > good to my eyes, deals with results of ADJUST-ARRAY as well, and > passes all my current test-cases. > > Anyone want to poke holes at it? It seems I get a compile-time error trying to apply that patch. See PS for backtrace. I'm trying to compile 1.0.27.30 from git with 1.0.5 as host. -T. ; compiling file "/src/tcr/contributing/sbcl-git/src/code/primordial-extensions.lisp" (written 16 SEP 2008 05:22:39 PM): ; compiling (IN-PACKAGE "SB!IMPL") ; compiling (DEF!CONSTANT +EMPTY-HT-SLOT+ ...) ; compiling (DEFUN FROB-DO-BODY ...) ; compiling (DEFMACRO DO-ANONYMOUS ...) ; compiling (DEFUN BLOCK-GENSYM ...)unhandled TYPE-ERROR in thread #<SB-THREAD:THREAD "initial thread" {A695B51}>: The value #<UNION-TYPE LIST> is not of type ARGS-TYPE. 0: (SB-DEBUG:BACKTRACE 128 #<SYNONYM-STREAM :SYMBOL SB-SYS:*STDERR* {90B57A9}>) 1: (SB-DEBUG::DEBUGGER-DISABLED-HOOK #<TYPE-ERROR {BE55499}> #<unavailable argument>) 2: (INVOKE-DEBUGGER #<TYPE-ERROR {BE55499}>) 3: (INVOKE-DEBUGGER #<TYPE-ERROR {BE55499}>) 4: (ERROR TYPE-ERROR) 5: (SB-KERNEL::OBJECT-NOT-TYPE-ERROR-HANDLER #<unavailable argument> #.(SB-SYS:INT-SAP #XB7AF20C4) #<SB-ALIEN-INTERNALS:ALIEN-VALUE :SAP #XB7AF1DAC :TYPE (* (SB-ALIEN:STRUCT SB-VM::OS-CONTEXT-T-STRUCT))> (14 78)) 6: (SB-KERNEL::OBJECT-NOT-TYPE-ERROR-HANDLER #<unavailable argument> #.(SB-SYS:INT-SAP #XB7AF20C4) #<SB-ALIEN-INTERNALS:ALIEN-VALUE :SAP #XB7AF1DAC :TYPE (* (SB-ALIEN:STRUCT SB-VM::OS-CONTEXT-T-STRUCT))> (14 78)) 7: (SB-KERNEL:INTERNAL-ERROR #.(SB-SYS:INT-SAP #XB7AF1DAC) #<unavailable argument>) 8: ("foreign function: #x806514C") 9: ("foreign function: #x8051E7C") 10: ("foreign function: #x805645C") 11: ("foreign function: #x8056D49") 12: (VALUES-TYPE-TYPES #<UNION-TYPE LIST> #<NAMED-TYPE NIL>) 13: (SB!KERNEL::ARGS-TYPE-OP #<UNION-TYPE LIST> #<MEMBER-TYPE NULL> #<FUNCTION TYPE-UNION> #<FUNCTION MIN>) 14: (SB!KERNEL::VALUES-TYPE-OP #<UNION-TYPE LIST> #<MEMBER-TYPE NULL> #<FUNCTION TYPE-UNION> #<FUNCTION MIN>) 15: (VALUES-TYPE-UNION #<UNION-TYPE LIST> #<MEMBER-TYPE NULL>) 16: (SB!C::LVAR-CONSERVATIVE-TYPE #<SB!C::LVAR 1 {BE17221}>) 17: (SB!C::CAR-DERIVE-TYPE-OPTIMIZER #<SB!C::COMBINATION :FUN #<SB!C::REF :LEAF # {BE15F91}> :ARGS ((# #)) {BE15FD1}>) 18: (SB!C::IR1-OPTIMIZE-COMBINATION #<SB!C::COMBINATION :FUN #<SB!C::REF :LEAF # {BE15F91}> :ARGS ((# #)) {BE15FD1}>) 19: (SB!C::IR1-OPTIMIZE-BLOCK #<SB!C::CBLOCK NIL :START c2 {BE52341}>) 20: (SB!C::IR1-OPTIMIZE #<SB!C:COMPONENT :NAME (SB!C::HAIRY-ARG-PROCESSOR BLOCK-GENSYM) :REANALYZE T {BE1CC69}> NIL) 21: (SB!C::IR1-OPTIMIZE-UNTIL-DONE #<SB!C:COMPONENT :NAME (SB!C::HAIRY-ARG-PROCESSOR BLOCK-GENSYM) :REANALYZE T {BE1CC69}>) 22: (SB!C::IR1-PHASES #<SB!C:COMPONENT :NAME (SB!C::HAIRY-ARG-PROCESSOR BLOCK-GENSYM) :REANALYZE T {BE1CC69}>) 23: (SB!C::COMPILE-COMPONENT #<SB!C:COMPONENT :NAME (SB!C::HAIRY-ARG-PROCESSOR BLOCK-GENSYM) :REANALYZE T {BE1CC69}>) 24: (SB!C::%COMPILE (LAMBDA (&OPTIONAL (NAME "G") (ENV (WHEN # #))) (BLOCK BLOCK-GENSYM (LET (#) (IF BLOCK-NAME # #)))) #<FASL-OUTPUT "/src/tcr/contributing/sbcl-git/obj/from-xc/src/code/primordial-extensions.lisp-obj-tmp">) 25: (SB!C::PROCESS-TOPLEVEL-COLD-FSET BLOCK-GENSYM (LAMBDA (&OPTIONAL (NAME "G") (ENV (WHEN # #))) (BLOCK BLOCK-GENSYM (LET (#) (IF BLOCK-NAME # #)))) ((COLD-FSET BLOCK-GENSYM (LAMBDA (&OPTIONAL # #) (BLOCK BLOCK-GENSYM #))) (PROGN (COLD-FSET BLOCK-GENSYM (LAMBDA # #)) (EVAL-WHEN (:COMPILE-TOPLEVEL) (SB!C:%COMPILER-DEFUN 'BLOCK-GENSYM 'NIL T)) (EVAL-WHEN (:LOAD-TOPLEVEL :EXECUTE) (%DEFUN 'BLOCK-GENSYM # NIL 'NIL ...))) SB!C::ORIGINAL-SOURCE-START 0 4)) 26: (SB!C::PROCESS-TOPLEVEL-FORM (COLD-FSET BLOCK-GENSYM (LAMBDA (&OPTIONAL (NAME "G") (ENV #)) (BLOCK BLOCK-GENSYM (LET # #)))) ((PROGN (COLD-FSET BLOCK-GENSYM (LAMBDA # #)) (EVAL-WHEN (:COMPILE-TOPLEVEL) (SB!C:%COMPILER-DEFUN 'BLOCK-GENSYM 'NIL T)) (EVAL-WHEN (:LOAD-TOPLEVEL :EXECUTE) (%DEFUN 'BLOCK-GENSYM # NIL 'NIL ...))) SB!C::ORIGINAL-SOURCE-START 0 4) NIL) 27: (SB!C::PROCESS-TOPLEVEL-PROGN ((COLD-FSET BLOCK-GENSYM (LAMBDA (&OPTIONAL # #) (BLOCK BLOCK-GENSYM #))) (EVAL-WHEN (:COMPILE-TOPLEVEL) (SB!C:%COMPILER-DEFUN 'BLOCK-GENSYM 'NIL T)) (EVAL-WHEN (:LOAD-TOPLEVEL :EXECUTE) (%DEFUN 'BLOCK-GENSYM (FDEFINITION 'BLOCK-GENSYM) NIL 'NIL ...))) ((PROGN (COLD-FSET BLOCK-GENSYM (LAMBDA # #)) (EVAL-WHEN (:COMPILE-TOPLEVEL) (SB!C:%COMPILER-DEFUN 'BLOCK-GENSYM 'NIL T)) (EVAL-WHEN (:LOAD-TOPLEVEL :EXECUTE) (%DEFUN 'BLOCK-GENSYM # NIL 'NIL ...))) SB!C::ORIGINAL-SOURCE-START 0 4) NIL) 28: (SB!C::PROCESS-TOPLEVEL-FORM (PROGN (COLD-FSET BLOCK-GENSYM (LAMBDA (&OPTIONAL # #) (BLOCK BLOCK-GENSYM #))) (EVAL-WHEN (:COMPILE-TOPLEVEL) (SB!C:%COMPILER-DEFUN 'BLOCK-GENSYM 'NIL T)) (EVAL-WHEN (:LOAD-TOPLEVEL :EXECUTE) (%DEFUN 'BLOCK-GENSYM (FDEFINITION 'BLOCK-GENSYM) NIL 'NIL ...))) (SB!C::ORIGINAL-SOURCE-START 0 4) NIL) 29: (SB!C::PROCESS-TOPLEVEL-FORM (DEFUN BLOCK-GENSYM (&OPTIONAL (NAME "G") (ENV (WHEN # #))) (LET ((BLOCK-NAME #)) (IF BLOCK-NAME (GENSYM #) (GENSYM NAME)))) (SB!C::ORIGINAL-SOURCE-START 0 4) NIL) 30: (SB!C::SUB-SUB-COMPILE-FILE #<SB!C::SOURCE-INFO >) 31: ((LAMBDA ())) 32: (SB!C::%WITH-COMPILATION-UNIT #<CLOSURE (LAMBDA #) {B47595D}>) 33: (SB!C::SUB-COMPILE-FILE #<SB!C::SOURCE-INFO >) 34: (SB-XC:COMPILE-FILE "src/code/primordial-extensions.lisp") 35: (SB-COLD::COMPILE-STEM "src/code/primordial-extensions" :OBJ-PREFIX "obj/from-xc/" :OBJ-SUFFIX ".lisp-obj" :TMP-OBJ-SUFFIX-SUFFIX "-tmp" :SRC-PREFIX "" :SRC-SUFFIX ".lisp" :COMPILE-FILE #<FUNCTION SB-XC:COMPILE-FILE> :TRACE-FILE NIL :IGNORE-FAILURE-P NIL) 36: (SB-COLD::IN-TARGET-CROSS-COMPILATION-MODE #<CLOSURE (LAMBDA #) {B43E59D}>) 37: (NIL) 38: (SB-INT:SIMPLE-EVAL-IN-LEXENV (LET ((SB-COLD::REVERSED-TARGET-OBJECT-FILE-NAMES NIL)) (SB-COLD::DO-STEMS-AND-FLAGS (SB-COLD::STEM SB-COLD::FLAGS) (UNLESS (POSITION :NOT-TARGET SB-COLD::FLAGS) (PUSH # SB-COLD::REVERSED-TARGET-OBJECT-FILE-NAMES))) (SETF SB-COLD::*TARGET-OBJECT-FILE-NAMES* (NREVERSE SB-COLD::REVERSED-TARGET-OBJECT-FILE-NAMES))) #<NULL-LEXENV>) 39: (SB-FASL::LOAD-AS-SOURCE #<SB-SYS:FD-STREAM for "file /src/tcr/contributing/sbcl-git/src/cold/compile-cold-sbcl.lisp" {ADA7321}> NIL NIL) 40: (SB-FASL::INTERNAL-LOAD #P"src/cold/compile-cold-sbcl.lisp" #P"/src/tcr/contributing/sbcl-git/src/cold/compile-cold-sbcl.lisp" :ERROR NIL NIL :SOURCE :DEFAULT) 41: (SB-FASL::INTERNAL-LOAD #P"src/cold/compile-cold-sbcl.lisp" #P"/src/tcr/contributing/sbcl-git/src/cold/compile-cold-sbcl.lisp" :ERROR NIL NIL NIL :DEFAULT) 42: (LOAD "src/cold/compile-cold-sbcl.lisp") 43: (SB-INT:SIMPLE-EVAL-IN-LEXENV (LOAD "src/cold/compile-cold-sbcl.lisp") #<NULL-LEXENV>) 44: (SB-EXT:INTERACTIVE-EVAL (LOAD "src/cold/compile-cold-sbcl.lisp")) 45: (SB-IMPL::REPL-FUN NIL) 46: (SB-IMPL::REPL-FUN NIL) 47: ((LAMBDA ())) 48: ((LAMBDA ())) 49: (SB-IMPL::%WITH-REBOUND-IO-SYNTAX #<CLOSURE (LAMBDA #) {A69D2B5}>) 50: (SB-IMPL::TOPLEVEL-REPL NIL) 51: (SB-IMPL::TOPLEVEL-INIT) 52: ((LABELS SB-IMPL::RESTART-LISP)) unhandled condition in --disable-debugger mode, quitting ; ; compilation unit aborted ; caught 1 fatal ERROR condition ; compilation aborted after 0:00:00.072 |
From: Nikodemus S. <nik...@ra...> - 2009-04-24 10:22:42
Attachments:
lvar-conservative-type-3.patch
|
2009/4/24 Tobias C. Rittweiler <tc...@fr...>: >> Anyone want to poke holes at it? > > It seems I get a compile-time error trying to apply that patch. See PS > for backtrace. I'm trying to compile 1.0.27.30 from git with 1.0.5 as > host. Uh, I actually never did a whole build with it -- just patched SBCL on the run. Sorry for not being explicit about that. The attached version has the advantage of actually building. Cheers, -- Nikodemus |
From: Nikodemus S. <nik...@ra...> - 2009-05-01 10:39:01
|
2009/4/24 Nikodemus Siivola <nik...@ra...>: > The attached version has the advantage of actually building. Merged as 1.0.28.2. > Cheers, > > -- Nikodemus |
From: Tobias C. R. <tc...@fr...> - 2009-04-25 09:35:33
|
Nikodemus Siivola <nik...@ra...> writes: > 2009/4/24 Tobias C. Rittweiler <tc...@fr...>: > >>> Anyone want to poke holes at it? >> >> It seems I get a compile-time error trying to apply that patch. See PS >> for backtrace. I'm trying to compile 1.0.27.30 from git with 1.0.5 as >> host. > > Uh, I actually never did a whole build with it -- just patched SBCL on > the run. Sorry for not being explicit about that. > > The attached version has the advantage of actually building. The patch does not guard against (defun foo (y) (declare (optimize safety)) (let ((x (cons 1 2))) (declare (type (cons fixnum fixnum) x)) (setf (car x) y) (+ (car x) (cdr x)))) And allowing just one LEAF reference is so simplistic that it may not make any difference in praxis. But of course, once it's there even though simplistic it can be improved in the future. :-) For example, the patch will inhibit deriving X,Y,Z to be of type FIXNUM in the following: (declaim (ftype (function (fixnum fixnum) (cons fixnum (cons fixnum (cons fixnum null)))) compute-fixed-list)) (defun compute-fixed-list (x y) (list (1+ x) (1- y) (+ x y))) (defun bar (y) (declare (optimize safety)) (destructuring-bind (x y z) (compute-fixed-list 1 y) (+ x y z))) For me that's the most obvious use case for specifying compound list types. -T. |
From: Nikodemus S. <nik...@ra...> - 2009-04-25 11:12:27
|
2009/4/25 Tobias C. Rittweiler <tc...@fr...>: > The patch does not guard against > > (defun foo (y) > (declare (optimize safety)) > (let ((x (cons 1 2))) > (declare (type (cons fixnum fixnum) x)) > (setf (car x) y) > (+ (car x) (cdr x)))) It's not intended to -- you're lying to the compiler. Inserting casts for things like that would be possible, but not in the general case: replace the (SETF CAR) with a call to FOO that does the same, and the compiler has no way to guard against it. (Ok, I suppose we could check the type again after any unknown call, but that would suck pretty badly -- not to mention that type TYPE-ERROR would arise after the damage has been done, which would be pretty wierd. The only thing that I can think of that could be done would be to never trust a specific CONS type or the dimensions of a non-simple ARRAY is safe code -- even if it is declared. Hm, yes, that might be a good idea. ...and note the wierdness of CONS and non-simple ARRAY types in the manual, of course... > And allowing just one LEAF reference is so simplistic that it may not > make any difference in praxis. But of course, once it's there even > though simplistic it can be improved in the future. :-) Yeah. There are probably a few case where it could be allowed -- like multiple CAR or CDR calls, but even then only if the type of CAR or CDR is not itself a "type that needs conservativism". Tricky, and I'm not quite convinced that it's worth the effort. > For example, the patch will inhibit deriving X,Y,Z to be of type FIXNUM > in the following: > > (declaim (ftype (function (fixnum fixnum) > (cons fixnum (cons fixnum (cons fixnum null)))) > compute-fixed-list)) > (defun compute-fixed-list (x y) > (list (1+ x) (1- y) (+ x y))) > > (defun bar (y) > (declare (optimize safety)) > (destructuring-bind (x y z) (compute-fixed-list 1 y) > (+ x y z))) > > For me that's the most obvious use case for specifying compound list > types. I believe the most common case is when you need to store pairs of fixnums and want to save one word as opposed to using (COMPLEX FIXNUM). I'll probably merge this patch as 1.0.28.early, and people who use (CONS FIXNUM) can then test it to see if they get performance regressions in their applications. Cheers, -- Nikodemus |
From: Tobias C. R. <tc...@fr...> - 2009-04-26 09:21:00
|
Nikodemus Siivola <nik...@ra...> writes: > 2009/4/25 Tobias C. Rittweiler <...>: > > > The patch does not guard against [violating DECLARE type declarations] > > Inserting casts for things like that would be possible, but not in the > general case: replace the (SETF CAR) with a call to FOO that does the > same, and the compiler has no way to guard against it. (Ok, I suppose > we could check the type again after any unknown call, but that would > suck pretty badly -- not to mention that type TYPE-ERROR would arise > after the damage has been done, which would be pretty wierd. > > The only thing that I can think of that could be done would be to > never trust a specific CONS type or the dimensions of a non-simple > ARRAY is safe code -- even if it is declared. Hm, yes, that might be a > good idea. Yes, or only trust it if you can be sure it's not going to be violated. (E.g. the variable is only passed to accessors functions, later perhaps to any function that is declared to be flushable---although I don't know how accurate the information is in fndb.) Bonus point if you can make it emit a note saying "forced to downgrade from more specific type (CONS FIXNUM (CONS FIXNUM NULL)) to LIST." on appropriate optimization settings. > ...and note the wierdness of CONS and non-simple ARRAY types in the > manual, of course... Section? (I looked through 3.2 but couldn't find it.) It would be useful if the manual was not only available one-site-per-node, but also everything-in-one-page. > > [DESTRUCTURING-BIND on return value declared to be (CONS FIXNUM ...)] > > > > For me that's the most obvious use case for specifying compound list > > types. > > I believe the most common case is when you need to store pairs of > fixnums and want to save one word as opposed to using (COMPLEX > FIXNUM). > > I'll probably merge this patch as 1.0.28.early, and people who use > (CONS FIXNUM) can then test it to see if they get performance > regressions in their applications. I've got a DEFTRANSFORM on PROPER-LENGTH-OF-LENGTH so DESTRUCTURING-BIND will complain at compile-time if the lambda-list does contain too many, or does not contain enough required parameters. E.g. (destructuring-bind (x y) (compute-fixed-list ...) ...) with the COMPUTE-FIXED-LIST of my previous message would result in a code deletion note. Furthermore, I modified DEFSTRUCT to use compound CONS specifiers for (defstruct (foo (:type list)) (a :type fixnum) (b :type fixnum) (b :type fixnum)) Now if you later add a new slot, or remove one, *all* the DESTRUCTURING-BINDs in my code will emit notes, and I can easily fix them appropriately. That's a nice poor man's algebraic-datatype like feature. Is that a good enough use case to see incentive to extend your work to make it probably derive types in DESTRUCTURING-BIND? :-) -T. |
From: Nikodemus S. <nik...@ra...> - 2009-04-26 10:29:03
|
2009/4/26 Tobias C. Rittweiler <tc...@fr...>: >> ...and note the wierdness of CONS and non-simple ARRAY types in the >> manual, of course... > Section? (I looked through 3.2 but couldn't find it.) Yeah. 33.2 is where I would put it -- haven't written it yet. > That's a nice poor man's algebraic-datatype like feature. ... > Is that a good enough use case to see incentive to extend your work to > make it probably derive types in DESTRUCTURING-BIND? :-) Unfortunately not in the short term at least: it would be nice to have, but looks like far more work for relatively marginal gains. Compiler bugs with potential for heap corruption (and wrong answers) are one thing, better type derivation for relatively marginal cases another. Cheers, -- Nikodemus |
From: Tobias C. R. <tc...@fr...> - 2009-04-27 08:30:50
|
Nikodemus Siivola <nik...@ra...> writes: > Compiler bugs with potential for heap corruption (and wrong answers) > are one thing, better type derivation for relatively marginal cases > another. Of course! Still thanks for your work so far! -T. |