On Nov 3, 2009, at 10:15 AM, Lisandro Dalcin wrote: > On Tue, Nov 3, 2009 at 3:06 PM, Dag Sverre Seljebotn > <[email protected]> wrote: >> Lisandro Dalcin wrote: >> >>> >>> Do you remember that I advocated for "ctypedef some int MyInt" or >>> something similar? If right now we had that, Cython could reject >>> some >>> things, like binops on different "ctypedef some .." types, requiring >>> users to introduce casts to resolve the ambiguity... A said it >>> before, >>> and I say it again: second-guessing is a bad thing (or, in Python's >>> Zen words: "In the face of ambiguity, refuse the temptation to >>> guess.") >>> >> I remember very well, and I've been thinking about it the whole >> day. I >> wholeheartedly agree with you that the situation is not good.
I think in generally this is an unsoveable problem as the Cython stage completes before the C stage starts (and generating code for all possible permutations isn't feasible in general). This means also that the author of the code doesn't (necessarily) know the size of the external types before C compile time, and they may change from platform to platform. We're still going to have to deal with this for function overloading (and there it's even nastier, as sizeof(a) >= sizeof(b) has different semantics from sizeof(a) == sizeof(b)). >> Another, perhaps more "backwards-compatible" approach is >> (backwards-compatible in the following sense: It will break code that >> should be broken and fixed, and not suddenly introduce bugs that are >> hard to find): >> >> a) Tighten down everything so that explicit casts are needed even >> for >> stuff like this: >> >> cdef long i >> cdef external_typedef_int j >> print i / j # not allowed, must do i / <long>j >> > > OK, +1 on this... I think this may be too much of a backwards incompatible change. Would one then have to do cdef external_typedef_int j print j / <external_typedef_int>2 print <long>j / 2 ? The phrase "should be broken and fixed" is somewhat subjective. Care should be taken when marking something that is potentially broken as something that is definitely broken. At the very least we should start with a directive that emits warnings or errors to see how much stuff it breaks and how constraining it is to work with first. Note that if we require casts, I can see people putting them in just to get their code to compile (without thinking of the full ramifications--or even if they do they might not know which of the two is actually wider, or it may be different on their system rather than their users). If this causes bugs down the line, it will be harder to track down than if it simply emitted an (optional or not) warning at that point. >> b) Add "exact" instead of "some" >> cdef extern ...: >> ctypedef long! mylong >> > > Well, I'm still thinking that "ctypedef int MyInt" should actually > mean exact... However, I realize that this is going to be a source of > code breakage. Lots of code breakage in Sage I could imagine. (And I don't think any of that code is actually broken, its stuff like flags (boolean ops count as arithmatic) or the mpfr precision type, etc. where size may be platform dependent but doesn't really need to be known). >> Code is then inserted during module loading which ensures >> sizeof(long) >> == sizeof(mylong). >> > > Mmm... Do "ensure" means a import failure? Perhaps a warning would > better? Perhaps a mismatch does not necessarily means the code is > broken... If you really want this (and it would seem to create highly non- portable code if you did, which mostly defeats the purpose of using external types in the first place) then you could stick an assert sizeof(long) == sizeof(mylong) right at the top of your module. Much more explicit, and needs no extra syntax. >> However I seem to remember that this was rejected as well by Robert >> (who, for some reason I can't understand, seems to think the current >> situation is OK.) > > Perhaps we were not clear enough at that time, and Robert rejected the > idea because it introduced new syntax? If I recall, my two primary concerns were that it was too large of a backwards incompatible change (at least to make it so by default right off), and that we hadn't come up with the right syntax yet. In particular, I really liked the idea of partially ranked types, so one could have short <= int <= long <= long long int16 < int32 < int64 int16 <= short ... which I think would make things much less painful, but we have yet to come up with a good way of specifying that. I think we're to the point that only ranking matters, not exact size. I'm more in favor of being able to specify a type as unranked, than have all extern types be unranked by default and having a keyword to specify types as exact. - Robert _______________________________________________ Cython-dev mailing list [email protected] http://codespeak.net/mailman/listinfo/cython-dev
