Re: More bugs...
On Tue, 01 May 2012 22:11:18 -0400, Mehrdad wrote: More problems... similar, but this time related to templates. struct Filter(R) { this(R) { } } template filter(R) { alias Filter!(R).__ctor filter; } void main() { filter([1, 2, 3]); } Error: template linq.filter(R) is not a function template It's an annoying limitation. IFTI specifically *only* works with functions. Not aliases, not types, not anything else. Functions only. -Steve
Re: More bugs...
On 05/02/12 04:11, Mehrdad wrote: > More problems... similar, but this time related to templates. > > struct Filter(R) { this(R) { } } > template filter(R) { alias Filter!(R).__ctor filter; } > void main() { filter([1, 2, 3]); } > > Error: template linq.filter(R) is not a function template > > > Why? Because it isn't? Where would 'R' come from in your example?... auto filter(R)(R r) { return Filter!R(r); } artur
Re: More bugs...
On 05/02/2012 04:14 AM, Mehrdad wrote: Yes, that non-global issue was the exact issue I was referring to. It drives me nuts whenever I try to give in and use templates. Regarding your "fix": Is it *really* intended that user should say arr.filter((typeof(some_random_expression) x) => x < y); instead of arr.filter(x => x < y); ? I think it's pretty obvious why that doesn't really work in practice... I agree that it should be fixed, but it is technically not a bug in the implementation.
Re: More bugs...
Yes, that non-global issue was the exact issue I was referring to. It drives me nuts whenever I try to give in and use templates. Regarding your "fix": Is it *really* intended that user should say arr.filter((typeof(some_random_expression) x) => x < y); instead of arr.filter(x => x < y); ? I think it's pretty obvious why that doesn't really work in practice...
Re: More bugs...
More problems... similar, but this time related to templates. struct Filter(R) { this(R) { } } template filter(R) { alias Filter!(R).__ctor filter; } void main() { filter([1, 2, 3]); } Error: template linq.filter(R) is not a function template Why?
Re: More bugs...
Yeah I just posted it yesterday. http://d.puremagic.com/issues/show_bug.cgi?id=8009 "Robert Clipsham" wrote in message news:jnoi6g$1f79$1...@digitalmars.com... On 01/05/2012 02:00, Mehrdad wrote: Some ICE for y'all. void filter(R)(scope bool delegate(ref BAD!R) func) { } void main() { filter(r => r); } Is this in bugzilla? It can't get fixed if no one knows about it! (Make sure to give it the ice keyword once you've submitted so it gets bumped to the top of the queue!) -- Robert http://octarineparrot.com/
Re: More bugs...
On 05/01/2012 01:20 PM, Mehrdad wrote: I guess the problem is with type deduction, but the trouble is that half the reason why type deduction is useful is in the case of lambdas. They become effectively useless if you have to type out their entire signature, since you could then just make them a separate function (or just use a mixin instead, to create a closure... which I've done before). This isn't really an 'enhancement', since the error message is clearly a bug. So I filed them both as bugs. http://d.puremagic.com/issues/show_bug.cgi?id=8009 http://d.puremagic.com/issues/show_bug.cgi?id=8010 The other bug I was referring to was something along the lines of the compiler telling me, "I can't really handle closures as template parameters very well (something about 'local variable' or whatever), so I'll just give you an obscure error every now and then". It only happened when it was inside another function, and some conditions were satisfied. (I don't remember the exact message, but when I searched it, I saw it had been already reported before...) Probably you mean this one: struct S{ int x; auto foo(alias a)(){return a(x);} } void main(){ auto s = S(2); int y = 3; writeln(s.foo!(x=>x+y)()); } Error: template instance foo!(__lambda2) cannot use local '__lambda2(__T1)' as parameter to non-global template foo(alias a) This is an arbitrary restriction and should be fixed. The 'this' pointer for 'foo' could be passed in a reserved slot at the beginning of the context for 'main'. Oh and thanks for the alternative, it's a good workaround to know. :) The trouble is that while it solves the bug I posted, it's still not solving my (actual) problem. The actual problem was that I wanted to do something along the lines of: private import std.range; auto filter(R, F)(R r, F f) { /*return a filtered range*/ } void main() { [1, 2, 3].filter(x => x < 3); } private import std.range; auto filter(R, F)(R r, F f) { /*return a filtered range*/ } void main() { [1, 2, 3].filter((int x) => x < 3); }
Re: More bugs...
On 01/05/2012 02:00, Mehrdad wrote: Some ICE for y'all. void filter(R)(scope bool delegate(ref BAD!R) func) { } void main() { filter(r => r); } Is this in bugzilla? It can't get fixed if no one knows about it! (Make sure to give it the ice keyword once you've submitted so it gets bumped to the top of the queue!) -- Robert http://octarineparrot.com/
Re: More bugs...
I guess the problem is with type deduction, but the trouble is that half the reason why type deduction is useful is in the case of lambdas. They become effectively useless if you have to type out their entire signature, since you could then just make them a separate function (or just use a mixin instead, to create a closure... which I've done before). This isn't really an 'enhancement', since the error message is clearly a bug. So I filed them both as bugs. http://d.puremagic.com/issues/show_bug.cgi?id=8009 http://d.puremagic.com/issues/show_bug.cgi?id=8010 The other bug I was referring to was something along the lines of the compiler telling me, "I can't really handle closures as template parameters very well (something about 'local variable' or whatever), so I'll just give you an obscure error every now and then". It only happened when it was inside another function, and some conditions were satisfied. (I don't remember the exact message, but when I searched it, I saw it had been already reported before...) Oh and thanks for the alternative, it's a good workaround to know. :) The trouble is that while it solves the bug I posted, it's still not solving my (actual) problem. The actual problem was that I wanted to do something along the lines of: private import std.range; auto filter(R, F)(R r, F f) { /*return a filtered range*/ } void main() { [1, 2, 3].filter(x => x < 3); } but I resorted to 'delegates' because this didn't work. However, when I did so, I decided to use a delegate anyway, while using 'scope' on the delegate and its parameter to avoid a heap allocation, but that didn't work either... so I just filed the bug report with a case that had less type inference. But the trouble is that the caller needing to say "delegate" is *already* too much typing, so the rest don't really help. :\ On 05/01/2012 04:02 AM, Mehrdad wrote: Wha..?! I can't believe delegates work so poorly in D... It is not the delegates, it is the type deduction algorithm for implicit function template instantiation. The issue is that the parameters do not cross-talk, which means R is not known during matching: How to detect the argument type from bool delegate(ElementType!R) alone if R is not known? The obvious solution would be to use an actual inference algorithm that uses information that can be gained from other parameters as well as information already known from the current parameter. You might want to file an enhancement request, because this exact thing seems to trip up many programmers. (i.e. it would be a lot more intuitive and convenient if it worked.) they're practically unusable unless you're passing them as template parameters (which brings on its own set of bugs)... I haven't encountered those so far. Seems like every time I try to escape a bug somehow, another one pops up :( The situation is improving. Furthermore, there is a very large subset of the language that is already very usable. Another way to make your code compile: private import std.range; void filter(R,S)(R, bool delegate(S)) if(is(S==ElementType!R)){ } void main() { [1, 2, 3].filter((int x) { return x < 3; }); }
Re: More bugs...
On 05/01/2012 04:02 AM, Mehrdad wrote: Wha..?! I can't believe delegates work so poorly in D... It is not the delegates, it is the type deduction algorithm for implicit function template instantiation. The issue is that the parameters do not cross-talk, which means R is not known during matching: How to detect the argument type from bool delegate(ElementType!R) alone if R is not known? The obvious solution would be to use an actual inference algorithm that uses information that can be gained from other parameters as well as information already known from the current parameter. You might want to file an enhancement request, because this exact thing seems to trip up many programmers. (i.e. it would be a lot more intuitive and convenient if it worked.) they're practically unusable unless you're passing them as template parameters (which brings on its own set of bugs)... I haven't encountered those so far. Seems like every time I try to escape a bug somehow, another one pops up :( The situation is improving. Furthermore, there is a very large subset of the language that is already very usable. Another way to make your code compile: private import std.range; void filter(R,S)(R, bool delegate(S)) if(is(S==ElementType!R)){ } void main() { [1, 2, 3].filter((int x) { return x < 3; }); }
Re: More bugs...
Wha..?! I can't believe delegates work so poorly in D... they're practically unusable unless you're passing them as template parameters (which brings on its own set of bugs)... Seems like every time I try to escape a bug somehow, another one pops up :( "Timon Gehr" wrote in message news:jnnfc6$2jve$2...@digitalmars.com... On 05/01/2012 03:46 AM, Mehrdad wrote: Is it just "weak", or is it outright wrong? Unfortunately it is by design that it does not work afaik. It's telling me "R" isn't a valid identifier... That one is a diagnostics bug.
Re: More bugs...
On 05/01/2012 03:46 AM, Mehrdad wrote: Is it just "weak", or is it outright wrong? Unfortunately it is by design that it does not work afaik. It's telling me "R" isn't a valid identifier... That one is a diagnostics bug.
Re: More bugs...
Is it just "weak", or is it outright wrong? It's telling me "R" isn't a valid identifier... "Timon Gehr" wrote in message news:jnnefl$2j69$1...@digitalmars.com... On 05/01/2012 03:09 AM, Mehrdad wrote: Also, what exactly is wrong with this code? private import std.range; void filter(R)(R, bool delegate(ElementType!R)) { } void main() { [1, 2, 3].filter(delegate bool(x) { return x < 3; }); } The current type deduction strategy for IFTI is (imho) too weak. private import std.range; void filter(R)(R, bool delegate(ElementType!R)) { } void main() { [1, 2, 3].filter!(int[])(delegate bool(x) { return x < 3; }); }
Re: More bugs...
On 05/01/2012 03:09 AM, Mehrdad wrote: Also, what exactly is wrong with this code? private import std.range; void filter(R)(R, bool delegate(ElementType!R)) { } void main() { [1, 2, 3].filter(delegate bool(x) { return x < 3; }); } The current type deduction strategy for IFTI is (imho) too weak. private import std.range; void filter(R)(R, bool delegate(ElementType!R)) { } void main() { [1, 2, 3].filter!(int[])(delegate bool(x) { return x < 3; }); }
Re: More bugs...
Also, what exactly is wrong with this code? private import std.range; void filter(R)(R, bool delegate(ElementType!R)) { } void main() { [1, 2, 3].filter(delegate bool(x) { return x < 3; }); }
Re: More bugs...
Some ICE for y'all. void filter(R)(scope bool delegate(ref BAD!R) func) { } void main() { filter(r => r); }
Re: More bugs...
On Sunday, 29 April 2012 at 06:22:34 UTC, James Miller wrote: D templates are analysed eagerly upon instantiation, whereas C++ templates are analysed lazily. This is not a bug, it is a feature. Furthermore, eager analysis is necessary for other D features like CTFE and compile-time reflection. Ah, I was wondering about that. Thank you for confirming. I will gladly ditch lazy template eval for something like CTFE. Honestly, in C++ I would stay away from code like the above anyway, irrelevant of whether it compiles, seems too "magic-y" for my tastes. I don't like things not being explicit. +1
Re: More bugs...
On Saturday, 28 April 2012 at 09:36:55 UTC, Timon Gehr wrote: On 04/28/2012 08:03 AM, Mehrdad wrote: You expected that to work? Uhm, why not? template struct F { F > f() { return F >(); } }; int main() { F().f().f().f().f().f(); // etc. return 0; } D templates are analysed eagerly upon instantiation, whereas C++ templates are analysed lazily. This is not a bug, it is a feature. Furthermore, eager analysis is necessary for other D features like CTFE and compile-time reflection. Honestly, in C++ I would stay away from code like the above anyway, irrelevant of whether it compiles, seems too "magic-y" for my tastes. I don't like things not being explicit. -- James Miller
Re: More bugs...
On 04/28/2012 12:05 PM, Max Samukha wrote: On Saturday, 28 April 2012 at 09:40:49 UTC, Timon Gehr wrote: On 04/28/2012 09:46 AM, Max Samukha wrote: On Saturday, 28 April 2012 at 06:03:54 UTC, Mehrdad wrote: You expected that to work? Uhm, why not? template struct F { F > f() { return F >(); } }; int main() { F().f().f().f().f().f(); // etc. return 0; } dmd is not smart enough DMD behaves according to the language specification here. That is not specified anywhere in the language specification. "Semantic analysis is not done until instantiated." On second thought, you are right, this is really badly phrased and does not say what it probably wants to. Anyway, the fact that templates are analysed fully eagerly upon instantiation is by design and the documentation should explicitly state that. to avoid recursion by treating f as a templated function. I am not sure whether it should, Maybe, but that would be a strange special case. That is arguable. If we are talking about the same thing, then it probably is not. I thought you were proposing to automatically templatise the function iff there is recursion? Non-templated functions are a special (degenerate) case of templated functions. How to 'instantiate' a non-templated function? This would necessarily be a supported operation, if there actually was such a relation between the two concepts. The way virtual functions work doesn't allow C++/D to fully implement that notion. That implies that the notion does not have merit. In D it was left out by design. And even C++ does not consistently implement it for non-virtuals. Mark f() 'virtual' in the C++ example and the code won't compile. I know. Furthermore, add an invalid member function to the templated struct F and don't refer to it. There won't be any compile time error. (unless it is virtual, of course!) Otherwise, C++ tries to be close to the ideal IMAO, it fails to be close to the ideal. and I would expect D be no worse. Yah, and it really is not. The other issue you brought up in this thread is certainly a real issue with the implementation though.
Re: More bugs...
On Saturday, 28 April 2012 at 09:40:49 UTC, Timon Gehr wrote: On 04/28/2012 09:46 AM, Max Samukha wrote: On Saturday, 28 April 2012 at 06:03:54 UTC, Mehrdad wrote: You expected that to work? Uhm, why not? template struct F { F > f() { return F >(); } }; int main() { F().f().f().f().f().f(); // etc. return 0; } dmd is not smart enough DMD behaves according to the language specification here. That is not specified anywhere in the language specification. to avoid recursion by treating f as a templated function. I am not sure whether it should, Maybe, but that would be a strange special case. That is arguable. Non-templated functions are a special (degenerate) case of templated functions. The way virtual functions work doesn't allow C++/D to fully implement that notion. Mark f() 'virtual' in the C++ example and the code won't compile. Otherwise, C++ tries to be close to the ideal and I would expect D be no worse. but the following should certainly work: struct F(T) { auto f()() { return F!(F!T)(); } } void main() { F!int().f().f().f(); } Error: struct a.F(T) recursive template expansion for template argument - why? The checking for infinite recursion seems to be too conservative here. You could open a bug report.
Re: More bugs...
On Saturday, 28 April 2012 at 09:36:55 UTC, Timon Gehr wrote: On 04/28/2012 08:03 AM, Mehrdad wrote: You expected that to work? Uhm, why not? template struct F { F > f() { return F >(); } }; int main() { F().f().f().f().f().f(); // etc. return 0; } D templates are analysed eagerly upon instantiation, whereas C++ templates are analysed lazily. This is not a bug, it is a feature. Having browsed several hundreds bug reports lately, I've seen a number of reports complaining that recursive templates instantiation failed. I've resisted the urge to comment that they were invalid. Although I do think they are invalid.
Re: More bugs...
On 04/28/2012 09:46 AM, Max Samukha wrote: On Saturday, 28 April 2012 at 06:03:54 UTC, Mehrdad wrote: You expected that to work? Uhm, why not? template struct F { F > f() { return F >(); } }; int main() { F().f().f().f().f().f(); // etc. return 0; } dmd is not smart enough DMD behaves according to the language specification here. to avoid recursion by treating f as a templated function. I am not sure whether it should, Maybe, but that would be a strange special case. but the following should certainly work: struct F(T) { auto f()() { return F!(F!T)(); } } void main() { F!int().f().f().f(); } Error: struct a.F(T) recursive template expansion for template argument - why? The checking for infinite recursion seems to be too conservative here. You could open a bug report.
Re: More bugs...
On 04/28/2012 08:03 AM, Mehrdad wrote: You expected that to work? Uhm, why not? template struct F { F > f() { return F >(); } }; int main() { F().f().f().f().f().f(); // etc. return 0; } D templates are analysed eagerly upon instantiation, whereas C++ templates are analysed lazily. This is not a bug, it is a feature.
Re: More bugs...
On Saturday, 28 April 2012 at 06:03:54 UTC, Mehrdad wrote: You expected that to work? Uhm, why not? template struct F { F > f() { return F >(); } }; int main() { F().f().f().f().f().f(); // etc. return 0; } dmd is not smart enough to avoid recursion by treating f as a templated function. I am not sure whether it should, but the following should certainly work: struct F(T) { auto f()() { return F!(F!T)(); } } void main() { F!int().f().f().f(); } Error: struct a.F(T) recursive template expansion for template argument - why?
Re: More bugs...
You expected that to work? Uhm, why not? template struct F { F > f() { return F >(); } }; int main() { F().f().f().f().f().f(); // etc. return 0; } Try thinking about your code before mouthing off here. Not trying to to be rude, but did you think about *your* reason before responding?
Re: More bugs...
On Saturday, 28 April 2012 at 04:45:59 UTC, Mehrdad wrote: Okay, final exams are coming up again, and so are my bugs (I have no idea what the correlation is, don't ask...) I guess I should post this on bugzilla, but oh well... I continued the thread instead. Try compiling this (I did this on Windows, DMD 2.059): void main() { Foo!(int[])([[1], [2]]); } struct Foo(T) { auto foo() { Foo!(T[]) t; return t; } } You expected that to work? Extra extra, infinite recursion is infinite! You are asking the compiler to instantiate Foo with the type int[], then use that type to instantiate Foo with int[][], which then instantiates Foo with type int[][][]. Try thinking about your code before mouthing off here. Would you fault C for causing a stack overflow in this case: int rec(int a){ return rec(a + 1); } I mean what did you expect, that the compiler could magically create infinite types? I can't even see where you might have gone wrong here, since the code is so simple. What I can see is that the constructor wouldn't work because there are no fields. I can see that you have some very strange ideas about templates, Foo(T) instantiates Foo(T[]), which is a different type, so it goes through and instantiates Foo(T[][]) which is, again, a different type. Think before declaring D to have bugs. -- James Miller
Re: More bugs...
Okay, final exams are coming up again, and so are my bugs (I have no idea what the correlation is, don't ask...) I guess I should post this on bugzilla, but oh well... I continued the thread instead. Try compiling this (I did this on Windows, DMD 2.059): void main() { Foo!(int[])([[1], [2]]); } struct Foo(T) { auto foo() { Foo!(T[]) t; return t; } }
Re: More bugs...
Oh sorry, here's the previous thread... somehow it got detached because of the subject line change: http://lists.puremagic.com/pipermail/digitalmars-d/2011-December/117172.html
Re: More bugs found in OS code
Adam D. Ruppe: > I do a lot. The way I do it is the arguments are made > available to the format, but it doesn't always need them > at runtime. > > string f = showNames ? "%1$s\t%2$d" : "%2$d"; > writefln(f, name, number); > > Though I don't literally use writefln for most > my code the same idea applies. Python is strict here: >>> "%d" % (1) '1' >>> "%d" % (1, 2) Traceback (most recent call last): File "", line 1, in TypeError: not all arguments converted during string formatting Even if you use that idiom, it has costs, measured in bugs. My experience tells me that a sloppy semantics, introduced or kept for a little convenience, always manages to find a way to bite your ass later. So I'd like more tidyness here. You are allowed to write: if (showNames) writeln("%1$s\t%2$d", name, number); else writeln("%2$d", name); There are also other solutions that don't compromise the already low safety of writeln, that is a dynamically typed isle in a statically typed language. Bye, bearophile
Re: More bugs found in OS code
On 11/02/2011 09:00 PM, Adam D. Ruppe wrote: bearophile: But how many times do you want to ignore some of the arguments listed? I do a lot. The way I do it is the arguments are made available to the format, but it doesn't always need them at runtime. string f = showNames ? "%1$s\t%2$d" : "%2$d"; writefln(f, name, number); Though I don't literally use writefln for most my code the same idea applies. If you use a literal format string, don't use indexed formatting and don't use all the args, I think it would be safe to call that a bug in most any case. Fail any one of those pre-conditions and you may have a point.
Re: More bugs found in OS code
bearophile: > But how many times do you want to ignore some of the > arguments listed? I do a lot. The way I do it is the arguments are made available to the format, but it doesn't always need them at runtime. string f = showNames ? "%1$s\t%2$d" : "%2$d"; writefln(f, name, number); Though I don't literally use writefln for most my code the same idea applies.
Re: More bugs found in OS code
Andrej Mitrovic: > Personally I like using this for a sort of on/off switch: > bool val; > // .. > val ^= 1; > > Maybe that's just stupid but I'm kind of used to it, lol. :p I use this, I think it's more explicit (but you have to state the variable name two times): val = !val; Bye, bearophile
Re: More bugs found in OS code
Adam D. Ruppe: > bearophile wrote: > > Currently this is not caught by D, it prints "12": > > import std.stdio; > > void main() { > >writefln("%d%d", 1, 2, 3); > > } > > That's not really an error. You might change out the format > string at runtime based on user preferences, perhaps for > internationalization, or other reasons. Right, the format string is in general a run-time value, so you can't always catch this situation at compile-time. But how many times do you want to ignore some of the arguments listed? Even if this happens (and I don't remember needing this), I think it's not common enough to justify so permissive semantics at run-time. Recently Andrei A. has expressed some opinions on this topic, but I don't remember the bug report number. Bye, bearophile
Re: More bugs found in OS code
Personally I like using this for a sort of on/off switch: bool val; // .. val ^= 1; Maybe that's just stupid but I'm kind of used to it, lol. :p
Re: More bugs found in OS code
bearophile wrote: > Currently this is not caught by D, it prints "12": > import std.stdio; > void main() { >writefln("%d%d", 1, 2, 3); > } That's not really an error. You might change out the format string at runtime based on user preferences, perhaps for internationalization, or other reasons.
More bugs found in OS code
The now usual article that advertises the PVS-Studio tool that shows plenty of (depressing) bugs found in already debugged source code of widely used C/C++ open source projects: http://software.intel.com/en-us/articles/90-errors-in-open-source-projects/ There is a Reddit discussion too, but I find it useless: http://www.reddit.com/r/programming/comments/lxjrb/examples_of_errors_detected_in_various_opensource/ In the Reddit discussion someone is free to list in D how many of the 91 bugs: - Are not applicable or are not normally done in D; - Are statically caught by D/DMD; - Are always caught at runtime by DMD in non release mode; - Are planned/discussed to be statically avoided or statically caught; - Are planned/discussed to be always caught at runtime by DMD in non release mode. Here I list and comment about some of the more interesting parts. Below I have divided the problems in 5 groups (I have not included all the bug groups shown in the article). A] Example 3. Fennec Media Project project. Complex expression. uint32 CUnBitArrayOld::DecodeValueRiceUnsigned(uint32 k) { ... while (!(m_pBitArray[m_nCurrentBitIndex >> 5] & Powers_of_Two_Reversed[m_nCurrentBitIndex++ & 31])) {} ... } The error was found through the V567 diagnostic: Undefined behavior. The 'm_nCurrentBitIndex' variable is modified while being used twice at single sequence point. MACLib unbitarrayold.cpp 78 Example 4. Miranda IM project. Complex expression. short ezxml_internal_dtd(ezxml_root_t root, char *s, size_t len) { ... while (*(n = ++s + strspn(s, EZXML_WS)) && *n != '>') { ... } The error was found through the V567 diagnostic: Undefined behavior. The 's' variable is modified while being used twice between sequence points.msne zxml.c 371 Currently DMD accepts this code: x = x++; Currently D is using the C semantics, this means the result of that line of code is undefined, this means you don't know what it will do once compiled by different D compilers or even with different optimization level on the same compiler. This means writing such code in C (and currently in D) is _always_ a bug (because a program with undefined semantics is often useless. There are other sources of undefined semantics, but the less there are, the better it is). I don't understand why C compilers don't refuse such code statically with an error. In my opinion this is not acceptable. Two basic solutions for D: 1) Define exactly what that code does in D. Walter has expressed few times his desire for this solution. 2) Turn similar lines of code into compile-time errors (and maybe accept them forever if the -d switch is used, but I am not sure this is a good idea). The first solution is good because it makes it simpler to port C code to D, it allows C/C++/Java programmers to use that code still. But such C code has undefined results, so I don't see a great advantage here (it's useful still to port Java code). But lately I am slowly leaning toward the second solution, because even if D defines exactly the semantics of code like this, so it gives the same result on all D compilers: (*(n = ++s + strspn(s, EZXML_WS)) && *n != '>') I don't want to read similar code in D programs I have to debug or modify. Even if it's unambiguous for the D language, it's a bit too much hard for me to understand. Go language has chosen this second solution. B] Curretly D2 accepts the usage of & and | among booleans: void main() { bool a, b; auto r1 = a & b; static assert(is(typeof(r1) == bool)); auto r2 = a | b; static assert(is(typeof(r2) == bool)); } But I am not sure this is useful enough to justify the risks that gives. Using booleans as integers is useful when I have to count them and in few other situations. But I don't remember the last time I've had to use bitwise or/bitwise and on boolean values, I think I have never had to do this. So maybe it's better to forbid this. The advantage of forbidding this operation is that it avoids several mistakes caused by operator precedence like (!x & y). Comments on this are welcome. C] Example 5. IPP Samples project. Priorities of ?: and | operations. vm_file* vm_file_fopen(...) { ... mds[3] = FILE_ATTRIBUTE_NORMAL | (islog == 0) ? 0 : FILE_FLAG_NO_BUFFERING; ... } The error was found through the V502 diagnostic: Perhaps the '?:' operator works in a different way than it was expected. The '?:' operator has a lower priority than the '|' operator. vm vm_file_win.c 393 Example 6. Newton Game Dynamics project. Priorities of ?: and * operations. dgInt32 CalculateConvexShapeIntersection (...) { ... den = dgFloat32 (1.0e-24f) * (den > dgFloat32 (0.0f)) ? dgFloat32 (1.0f) : dgFloat32 (-1.0f); ... } The error was