[HN Gopher] Google broke a conditional statement that verifies p...
       ___________________________________________________________________
        
       Google broke a conditional statement that verifies passwords on
       Chrome OS
        
       Author : stalfosknight
       Score  : 139 points
       Date   : 2021-07-22 18:32 UTC (4 hours ago)
        
 (HTM) web link (arstechnica.com)
 (TXT) w3m dump (arstechnica.com)
        
       | jeffbee wrote:
       | This is clearly a typo that happened to stomp some logic that is
       | not covered by a test. The review 3002282 includes the bug, which
       | deletes one of the & from a && operator. It says it was cherry-
       | picked from review 2994464, which does not change that line. So,
       | slip of the backspace key plus poor testing.
        
         | tyingq wrote:
         | Yeah, the biggest thing to me here is that there's no "login
         | succeeded" unit test, integration test, manual test, etc.
         | Whatever customer logged in first was the first person to
         | actually run the code.
        
       | SahAssar wrote:
       | Just reading the title it sounded very much like "Single Point of
       | Failure: The (Fictional) Day Google Forgot To Check Passwords":
       | https://www.youtube.com/watch?v=y4GB_NDU43Q
        
         | jedimastert wrote:
         | I love Tom's speculative fiction talks. He tells such a good
         | story.
        
       | lmilcin wrote:
       | Umm... no automated tests? Junior engineers responsible for
       | security of half of the world without proper code review?
        
         | tpmx wrote:
         | Half of the world? We're talking primarily north-american
         | school kids.
         | 
         | https://trends.google.com/trends/explore?q=chromebook
        
       | wil421 wrote:
       | Can the link be updated to the one below? The link above goes
       | directly to the comments section and collapses the article,
       | ?comments=1 is the culprit.
       | 
       | https://arstechnica.com/gadgets/2021/07/google-pushed-a-one-...
        
         | stalfosknight wrote:
         | HN won't let me edit the URL. :/
        
           | wil421 wrote:
           | Dang or someone else will probably see it. I didn't think
           | you'd be able to do it yourself.
        
         | dang wrote:
         | Fixed now. Thanks!
        
       | dboreham wrote:
       | This has happened so many times in recent years to high profile
       | services and OSes. You'd think it'd be a test case.
        
       | black_puppydog wrote:
       | That's not "bricking" as the title suggests. Sorry, word police
       | incoming. :P
        
       | snvzz wrote:
       | What it means is: They push crap to users with no testing.
       | 
       | Testing would have caught this.
        
         | schemescape wrote:
         | Maybe pushing updates to users _is_ their test process? I doubt
         | they 're the only ones doing this, sadly.
        
       | [deleted]
        
       | Traster wrote:
       | I bet the post-mortem for this is going to be fun. How this
       | wasn't covered by multiple unit tests, a code review and a roll
       | out strategy is.... impressive.
        
         | sneak wrote:
         | Bitwise & versus logical && is a classic, right up there with
         | an assignment in a comparison (when an equality check is
         | intended), = for ==.
         | 
         | That this was missed is pretty surprising, given that it's
         | Google and the stakes involved in the encryption/key management
         | code in a secure platform device.
         | 
         | I wonder if we'll even get a postmortem, as this simply cannot
         | happen unless several someones all Seriously Fucked Up
         | simultaneously.
         | 
         | - code error (expected, humans are fallible)
         | 
         | - review error (less expected, this is the kind of thing code
         | review exists for)
         | 
         | - static analysis / linting check failure
         | 
         | - integration test failure (interactive login no longer works
         | on this build)
         | 
         | This is a massive, overlapping fuckup. Heads should probably
         | roll here, especially given that when you opt in to ChromeOS as
         | a user, Google now has "one job" (DFIU).
        
           | nogridbag wrote:
           | I've seen the = instead of == in the wild with disastrous
           | results: the assignment was on an ORM backed object, e.g.
           | // accidentally mutates all names to Sam and persists to the
           | DB         myList.filter { myDomainObj.name = 'Sam' }
           | 
           | But it makes me wonder why our programming languages would
           | use characters which can often lead to this type of error.
        
             | sneak wrote:
             | If you consider a linter part of a programming language,
             | most, when properly configured, do not permit this. It's
             | just the syntax that does; professionals do not rely on
             | syntax validity alone but employ linting, code review,
             | static analysis, and integrations tests on top.
             | 
             | The gradient of professionalism in our industry is very
             | wide, and the slope is quite shallow.
             | 
             | To your point, however, many languages (such as Go,
             | developed and used by Google, the organization under
             | discussion) have designed their syntax now to completely
             | avoid this type of error even being possible.
        
               | galangalalgol wrote:
               | what is the difference between linting and static
               | analysis? Coverity, cppcheck etc, what are those? You
               | mention integration tests, but not unit test, do you
               | value unit test?
        
               | tmp_anon_22 wrote:
               | > type of error even being possible
               | 
               | I mean its still possible to forget the ":" character and
               | its still possible to mentally scan a PR and see "=" and
               | miss that it should have been a "==".
        
               | edflsafoiewq wrote:
               | = vs == isn't possible in Go because of the
               | statement/expression distinction. The benefits of
               | allowing assignment to be an expression are too small
               | compared to the problems it causes.                 x ==
               | 1 // oops, meant =       // x == 1 evaluated but not used
               | if x = 1 { ... } // oops, meant ==       // syntax error:
               | assignment x = 1 used as value
        
             | nightfly wrote:
             | I'm a fan of programming languages using := for assignment
             | for this reason
        
               | AnimalMuppet wrote:
               | Look, I know that this is an enormously bad bug, but...
               | 
               | Google has a codebase that numbers multiple billions of
               | lines. Using := means typing multiple billions of extra
               | characters. That adds up. And it wouldn't even have
               | prevented this bug!
               | 
               | All checks have costs. As Emerson said, "A stitch in time
               | saves nine. So we make 1000 stitches, that by doing so we
               | may save nine."
        
               | anyfoo wrote:
               | Once more I hope this is satire, but as so often on the
               | Internet it is surprisingly hard to tell.
        
               | samtheprogram wrote:
               | This reminds me of Silicon Valley's main character
               | preferring tabs to spaces because they use less bytes,
               | despite his own product being for... compression!
               | 
               | I personally prefer spaces so that under any
               | circumstances, the code reads the same as the author
               | intended (whether you're in an editor or viewing a file
               | with a CLI tool). Are we really counting bytes in this
               | day and age?
        
             | anyfoo wrote:
             | The problem is not even with "easy to mix up operators" for
             | this, it's about languages without a strong and static
             | enough type system. While the particular problem Google hit
             | is a bit more subtle (involving undefined behavior), in the
             | majority of cases a strongly typed language would not allow
             | expressions that accidentally mix up = and ==, as they
             | often resolve to different types.
             | 
             | In C "if (foo = bar)" and "if (foo == bar)" are both legal,
             | because pretty much any type can be automatically coerced
             | into a boolean. In many modern languages that is not the
             | case. (Of course if you have assignments as expressions you
             | are still screwed if foo and bar are both boolean to begin
             | with, so some languages got away with that, too. And for
             | fairness I should say that C at the very least warns if you
             | don't explicitly put parentheses around the assignment,
             | nowadays.)
        
               | crazygringo wrote:
               | > _in the majority of cases a strongly typed language
               | would not allow expressions that accidentally mix up =
               | and ==, as they resolve to different types._
               | 
               | That's not true at all.
               | 
               | Whenever you're intending to compare equality, they're
               | usually going to be the same type _already_ unless you
               | 're being really slopping in a scripting language like
               | JavaScript or PHP -- but even then they're _usually_ two
               | numbers, two strings, or two booleans.
               | 
               | The whole problem here is where foo and bar are _both_
               | integers, or booleans, or whatever you want, and instead
               | of typing  "if (foo == bar)" you type "if (foo = bar)".
               | 
               | Strong typing does _nothing whatsoever_ to help in this
               | common situation.
        
               | anyfoo wrote:
               | No. It can help because the _result_ of the expression
               | would have a different type, one that  "if" does not
               | accept. If a and b are integers, then the expression "a =
               | b" is an integer too, but "a == b" is a boolean. In a
               | strongly typed language, you can assume that "if" only
               | accepts booleans.
        
           | Guidii wrote:
           | "Heads should probably roll here..."
           | 
           | Google has a blameless post-mortem process (see
           | https://sre.google/sre-book/postmortem-culture/) which
           | essentially boils down to:
           | 
           | 0) We want to fix the situation. By the time the post-mortem
           | happens, that should already be done.
           | 
           | 1) We want to make sure this never happens again. In order to
           | do that we need to understand as much as we can about what
           | happened.
           | 
           | 2) We want everyone to share everything they know about the
           | event. If the participants worry about fallout, they will be
           | compelled to cover up.
           | 
           | 3) Most failures happen at a number of points, so you need to
           | dig in deeply if you want to get full value out of the
           | "event".
           | 
           | 4) Good post-mortems lead to process fixes to reduce (or
           | eliminate?) the chance of similar events, or to make fixes
           | throughout the code base.
           | 
           | The other thing is that after the post-mortem, all of the
           | folks involved have learned from it. Usually they're better
           | engineers because of that expensive lesson you've just paid
           | for.
           | 
           | Disclaimer: Googler, participant in several post-mortems,
           | opinions my own.
        
           | agilob wrote:
           | RedHat once committed wrong value of MTWO variable, it was 2,
           | there was another variable called TWO which also had value of
           | 2. It was fixed a few months later with a commit like "change
           | value of MTWO to -2".Sorry, but can't find it find now
        
           | james_in_the_uk wrote:
           | Straight up negligence.
        
           | kps wrote:
           | I'm quite surprised there isn't a compiler warning for a
           | bitwise operator at the root of a condition. I've been
           | writing `if ((flags & FLAG) != 0)` for decades years for
           | nothing?!?
        
           | fierro wrote:
           | _glances at screen_ LGTM
        
           | brundolf wrote:
           | Especially since it's so easy to lint for. This isn't some
           | cross-file memory mishandling bug, it's a single token that's
           | being used where it shouldn't be
        
           | mdoms wrote:
           | > Heads should probably roll here,
           | 
           | I disagree. It's obviously a major balls up by multiple
           | people, but at the end of the day this is an organizational
           | failure. You don't fire people for this, you learn from it
           | and fix the organizational holes that caused it.
        
             | sneak wrote:
             | Someone is responsible for the organizational units and
             | their processes.
             | 
             | By that logic, almost no individual failure is a firing
             | offense. Many people in the organization are responsible
             | for ensuring that the processes themselves overlap in ways
             | that exclude the possibility of failures like this.
             | 
             | I'm talking about the meta-failure in management's
             | oversight of the processes. There is belt person, and there
             | is suspenders person, and there is a third person who makes
             | sure there are both belt person and suspenders person on
             | staff and that they don't go on vacation at the same time.
             | 
             | Somewhere above the team lead and below the CEO there is
             | someone who didn't do their job.
        
               | nicoburns wrote:
               | > By that logic, almost no individual failure is a firing
               | offence
               | 
               | I'd probably agree with that. Firing should be for
               | extreme negligence, or sustained underperformance.
        
               | idiotsecant wrote:
               | >extreme negligence
               | 
               | If this doesn't qualify, what does?
        
               | vlovich123 wrote:
               | This isn't extreme negligence of any single individual.
               | If there are linters/compiler warnings that should have
               | caught this, this is an organizational failure that can
               | be remedied and the manager/TL should be taking a bit of
               | a hit here as having those enabled is best practices.
               | Since it's ChromeOS I imagine there's a dedicated team
               | managing the build infra and it's not using the base set
               | of things that Google3 protects you with, so the fault
               | may lie in that organization a bit as an oversight.
               | 
               | Then there's obviously the automated testing strategy,
               | manual testing strategy and sanitizer strategy that
               | missed this.
               | 
               | The net result is extreme negligence but to me this kind
               | of failure speaks to several layers going wrong at once
               | rather than one person fucking up badly. Organizationally
               | you try to defend against these kinds of failures with
               | multiple layers of defenses.
               | 
               | Now if this was a malicious internal attack that should
               | be investigated but I'd hate to have to seriously
               | reprimand anyone who typo'ed & instead of &&.
        
               | ectopod wrote:
               | The GGGP is talking about failures at a higher level. Not
               | reprimanding the coder who missed an ampersand, but the
               | manager who was ultimately responsibly for ensuring there
               | was a functioning process for catching this sort of
               | nonsense.
        
               | sneak wrote:
               | I would say this is negligence, but perhaps not extremely
               | so.
        
               | anyfoo wrote:
               | You are all very quick to judge. I don't work for Google
               | so I don't know what happened, but consider the
               | possibility that this may have been a freak accident.
               | That piece of code for example might only be on a path
               | that is not activated when testing, or it may be executed
               | but not have the same fatal effect.
               | 
               | And before anyone comes along and says "well, every
               | possible path should be tested then": That would be
               | absolutely impossible even if the halting problem wasn't
               | a thing (which it very much is). Even if you somehow have
               | utopian "100% code coverage", that does not mean you have
               | tested every possible input resulting in every possible
               | state combination.
               | 
               | I bet every one of us has a story about an old bug that
               | only manifested years[1] later because of the confluence
               | of many unfortunate things, one that takes half an hour
               | to tell.
               | 
               | [1] Or even decades, in some cases that then made it to
               | the HN front page.
        
               | nicoburns wrote:
               | This is the sort of thing that most linting tools will
               | catch, so it's a bit worse than that I think. You
               | shouldn't need _any_ test coverage to catch this.
        
               | admax88q wrote:
               | The way you fix organizational/process failures is not by
               | firing the person in charge of them every time they fail
               | to catch something.
               | 
               | How many breaking bugs have _NOT_ shipped due to the
               | current processes. Your approach suggests that there is
               | some perfect process manager out there who will let no
               | bugs like this ship (whilst not dropping any other
               | business priorities mind you) that they just haven't
               | hired yet into this position.
               | 
               | This isn't as big of a bug as people on HN want it to be.
               | A few months from few people will remember, and even
               | fewer will care.
        
               | AnimalMuppet wrote:
               | There is a story (perhaps apocryphal) of a salesman who
               | lost a $10 million deal for IBM. He was sure he was going
               | to be fired. Some bigwig (Watson himself, maybe?) talked
               | him through what had gone wrong. The salesman asked,
               | "Aren't you going to fire me?" The bigwig said, "I just
               | spent 10 million dollars training you."
        
               | yupper32 wrote:
               | > By that logic, almost no individual failure is a firing
               | offense.
               | 
               | That's pretty close to how it should be. That's the core
               | premise of the no-blame post-mortem culture that's great
               | about some companies.
               | 
               | As long as you go through the port-mortem process, which
               | includes doing your best to prevent this from happening
               | again (which may include changing organizational
               | processes, testing strategies, etc), then everyone can
               | move on with their lives.
               | 
               | Firing happens when you have a history of performing
               | below your level. Never for a single engineering failure.
        
               | sneak wrote:
               | This isn't an engineering failure. Everyone writes bugs.
        
               | yupper32 wrote:
               | Engineering process is still engineering in my book, but
               | if it helps:
               | 
               | Firing happens when you have a history of performing
               | below your level. Never for a single process failure.
        
               | mdoms wrote:
               | > By that logic, almost no individual failure is a firing
               | offense.
               | 
               | Correct.
        
             | aeturnum wrote:
             | I don't think we know enough from this to say.
             | 
             | It's possible that this bug made it into the wild because
             | the organizational structure made remedies impossible. In
             | that case you probably don't fire anyone, though maybe you
             | reassign some folks.
             | 
             | It's also possible that the organizational structure
             | indicates that a person or a group of people is responsible
             | for this and they failed to do that job. If that's the case
             | then it might very well make sense to fire folks. It also
             | might not.
             | 
             | I think it's important for poor performance to have
             | consequences[1] and I also think that people leave jobs all
             | the time and it's fine to decide that someone should leave
             | their place in the org with a positive reference and look
             | elsewhere for work (perhaps in another part of goog).
             | 
             | [1] for moral and company culture reasons if nothing else.
        
         | chovybizzass wrote:
         | i've never worked on a project (even TDD) that did that level
         | of testing detail.
        
       | contravariant wrote:
       | Wait so are the devices bricked or not? The title says bricked
       | but as far as I can tell people just can't log in temporarily
       | until the fix is rolled out.
        
         | penagwin wrote:
         | It's a soft lock for sure, given it requires a software update
         | to use you could likely consider this a soft brick too.
         | 
         | It's not a hard brick to your point.
        
         | dang wrote:
         | Ok, we've done our bit to counter brick dilution in the title
         | above.
        
         | sneak wrote:
         | No, they are not bricked. The term has become ridiculously
         | diluted in practice to mean "hard, breaking bug".
        
       | secondcoming wrote:
       | Edit: Someone has explained the issue below
       | 
       | I don't understand how that broke anything?
       | 
       | The C++ codegen for && and & is the same:                   bool
       | good(bool a, bool b) { return a && b; }              good(bool,
       | bool):                                           mov     eax, edi
       | and     eax, esi             ret                   bool bad(bool
       | a, bool b) { return a & b; }              bad(bool, bool):
       | mov     eax, edi             and     eax, esi             ret
       | 
       | [0] https://godbolt.org/z/84MMqTehs
        
         | taeric wrote:
         | The short circuiting was preventing undefined behavior on the
         | second expression.
         | 
         | That is, yes, it is the same with booleans. Now try with
         | expressions.
        
         | formerly_proven wrote:
         | The code is:                   key_data.has_value() &&
         | !key_data_->label().empty()
         | 
         | key_data is probably something like an std::optional, so short-
         | circuit evaluation guards the dereferencing of the optional. If
         | you write this with a binary and, no short-circuit evaluation
         | can happen, so undefined behavior ensues.
         | 
         | I wanna point out that std::optional, in the typical C++
         | stance, has a "I know what I'm doing" API and a "Humans make
         | mistakes API": optional->... is UB if the optional is empty,
         | optional.value()... raises an exception. Arguably, in code like
         | this you probably only want to use the latter kind of API. (The
         | pattern of "operator can UB, equivalent method asserts pre-
         | condition" is very common in the C++ standard library)
        
           | jeffbee wrote:
           | Correct, key_data_ is a base::Optional<KeyData>. Chromium's
           | base::Optional is very similar to std::optional, but predates
           | c++17.
        
         | tmiahm wrote:
         | The difference is your example uses bool values, the code in
         | question uses expressions that (should) evaluate to bool. && is
         | short-circuited if a is false, such that b is not evaluated.
        
         | [deleted]
        
       | skinkestek wrote:
       | The company who no longer recognizes doublequotes nor their own
       | verbatim operator?
       | 
       | The one who flags chess videos?
       | 
       | Closes decade old accounts without any kind of explanation?
       | 
       | Absolutely believable.
       | 
       | Wouldn't surprise if this too is related to relying on their
       | Artificial Stupidity^HIntellingence systems.
        
       | iamcreasy wrote:
       | The article says the problem bricked their laptop - but I was
       | under the assumption that you can create a non-google
       | account/guest account on Chrome OS to use the device.
        
       | tuxoko wrote:
       | I haven't touched C++ in forever, but as a C programmer it looks
       | insane that you can do dot operator and -> operator on the same
       | variable and not cause compiler error...
        
       | tyingq wrote:
       | I'm baffled that there's no test for this, manual or otherwise,
       | before this rolls out to production. That you can change ChromeOS
       | code in the login path, and the very first time it's exercised is
       | by an end customer.
        
       | mouzogu wrote:
       | Couldn't this be caused by a bad merge?
       | 
       | Not sure how Google manages their merging and release process but
       | there are conceivably several stages where a bad merge can occur
       | and go unnoticed - possibly at a stage close to release and after
       | testing.
        
         | tmp_anon_22 wrote:
         | At an established company merging is an incredibly incredibly
         | locked down process. There are usually multiple barriers of
         | automation and people, entire release teams who all have to be
         | stoned at the wheel to miss anything odd getting through.
        
       | fouric wrote:
       | From the article:
       | 
       | > The line should read "if (key_data_.has_value() &&
       | !key_data_->label().empty()) {" but instead of "&&"--the C++
       | version of the "AND" operator--the bad update used a single
       | ampersand, breaking the second half of the conditional statement.
       | 
       | Someone correct me if I'm wrong, but this seems like it wouldn't
       | be possible in a language that didn't conflate boolean values
       | with bitvectors.
       | 
       | Edit: I was wrong[1].
       | 
       | [1] https://news.ycombinator.com/item?id=27923785
        
         | CobrastanJorji wrote:
         | Forgive my poor C++, but has_value() sounds like a bool, and
         | empty() sounds like a bool. Why wouldn't "bool1 & bool2" work
         | correctly?
        
           | kevinmgranger wrote:
           | If I had to guess, the second expression depends on the first
           | being true. So if `has_value()` is false, perhaps
           | `key_data_->label()` is undefined behavior.
        
           | dataflow wrote:
           | Dereferencing via key_label_-> has undefined behavior when
           | !key_label_.has_value(), so the compiler treats that case the
           | same as if key_label_.has_value(). Or to put it another way,
           | the compiler reasons that key_label_ must have had a value
           | (since you dereferenced it), and thus optimizes out the check
           | for `has_value()` (since clearly it was unnecessary).
        
             | myko wrote:
             | Would this optimization not have been on the beta/canary
             | channel? I assumed they were but perhaps not since this was
             | not caught.
        
               | dataflow wrote:
               | I don't know how their builds work or where their
               | templates are instantiated but it's possible that the
               | compiler doesn't see this optimization until LTO and that
               | they don't do LTO until stable releases? It would seem
               | strange though, I'd have thought beta would have LTO.
        
               | anyfoo wrote:
               | Yeah that would be a very weird choice. LTO itself can
               | have bugs, or (as we speculate here) unmask existing
               | bugs. Plus, even that aside, you'd hopefully test exactly
               | the build that you will release before you release it.
               | 
               | As I wrote in another comment, this could still be the
               | result of a freak accident and not have shown up in
               | testing, though (but since I know nothing about the
               | process or the code there, it could be anything).
        
             | fouric wrote:
             | Ahhh, so it was a problem with lazy evaluation (and the
             | lack thereof when using &), and not type coercion, like I
             | initially thought.
        
               | kbelder wrote:
               | I think this is a unpopular opinion, but I consider
               | taking advantage of short-circuiting in boolean
               | operations to be a code smell. At least for me, it seems
               | very fragile and I'd much rather break the conditional
               | logic out explicitly.
               | 
               | But I like to write as much like assembly as I can in
               | every language. Each line of code should do one and only
               | one thing.
        
               | dataflow wrote:
               | I used to only put short-circuits when I really needed
               | short-circuit behavior, thinking it improved readability.
               | But after getting by the implicit type conversions over
               | and over (as well as nags from every compiler) I just
               | decided it was a bad idea in C++. I'd still do it in a
               | safer language, but in C++ I'm convinced you should just
               | use && even when you only need & for bools.
        
               | dataflow wrote:
               | Yeah it has nothing to do with type coercion. I'm baffled
               | a linter doesn't catch this though. & for bools should
               | just be prohibited altogether. If people really want &
               | for bool, they can just cast to an integer type and use &
               | with that (which generates its own warnings
               | appropriately).
        
               | gpderetta wrote:
               | the problem is that bitwise & and | are routinely used
               | for their non-shortcircuiting behaviour in boolean
               | expressions, so it is hard for the compiler to flag this
               | as an error.
               | 
               | Many linters and static analysis tools do flag them
               | though as these days it is not considered good practice.
        
               | anyfoo wrote:
               | Why would you even need non-shortcircuiting behavior in
               | boolean expressions? Because either side of the operator
               | has side effects that you want to happen unconditionally?
               | Please just write it out as an extra statement then
               | instead of hammering it into place with an implicit
               | coercion to an integer type only so you can abuse bitwise
               | AND and OR only to force that side effect to... you can
               | see why this is probably not the most elegant idea.
        
               | slavik81 wrote:
               | Matt Godbolt gave an example of a significant performance
               | hit caused by unnecessary short-circuiting in his CppCon
               | 2019 talk[1]. EDIT: Deleted tangent.
               | 
               | [1]: https://youtu.be/HG6c4Kwbv4I?t=45m
        
               | dataflow wrote:
               | > & and | are routinely used for their non-
               | shortcircuiting behaviour in boolean expressions
               | 
               | Really? I can't recall a single case of this with 'bool'
               | in any codebase in my recent memory. I only see it with
               | integers. And even if it's somehow routine for your
               | codebases with bool (why?!), surely it's not routine
               | inside a _conditional expression_ , so at least they can
               | prohibit it there?
        
             | xmprt wrote:
             | So instead of short circuiting like that code should when
             | it uses &&, it instead makes an assumption about the first
             | part of the boolean expression because otherwise the code
             | would have undefined behavior?
        
               | dataflow wrote:
               | Yeah. More specifically, it just inserts whatever
               | behavior it likes for the undefined scenario, which in
               | this case is "the same behavior as in the defined
               | scenario".
        
         | grishka wrote:
         | Certainly won't compile in Java.
        
           | taeric wrote:
           | Oddly... It would? Try:                   Map<String,
           | Boolean> map = ...         if (map.containsKey("hello") &
           | map.get("hello")) { ...
        
           | shawnz wrote:
           | In fact you can apply the single ampersand & operator to
           | booleans in Java, and just like in the example here it has
           | the same behaviour as && but with no short-circuiting.
        
             | grishka wrote:
             | Huh. I didn't know that.
        
         | wyager wrote:
         | The most general solution here is to use algebraic types and
         | pattern match on the value being "None" or "Some data".
        
         | Trollmann wrote:
         | You can use `and` and its siblings instead of && and similar in
         | C++11. Most people here, and in other boards, will try to
         | convince you that it hurts readability because 'that's how we
         | always did it' (read I'm used to it and don't like change).
        
           | gavinray wrote:
           | I was surprised to read that `and`, `and_eq`, `xor`, etc are
           | all supported "secondary/alternative operators"
           | 
           | Never seen them used, but I use them in my C++ code when I
           | have to write it to accomplish something else:
           | 
           | https://en.cppreference.com/w/cpp/language/operator_alternat.
           | ..
        
             | inetknght wrote:
             | I used to use them. Then I was burned by some Very
             | Opinionated managers and coworkers who didn't like seeing
             | new things. It wasn't a hill I was willing to die on;
             | there's more important things to argue about in C++.
        
           | fouric wrote:
           | I am also of the opinion that `and` is more readable than
           | `&&` (and isn't as easy to typo in a catastrophic way) -
           | although my main point was about the weaker type system.
        
             | qalmakka wrote:
             | C++ definitely hasn't a weaker type system than "newer"
             | languages like Java - if any, it is much more richer and
             | complex than most languages out there. What's happening
             | here is a type conversion that has to be in place due to C
             | not having a boolean type until 1999. C++ attempts to
             | construct a boolean from the argument of an `if()`, and
             | given that bool can be constructed from int, the conversion
             | succeedes.
             | 
             | You can define your own conversion operators to boolean,
             | too, which are very useful for stuff like smart pointers
             | and similar classes that may or may not have a value.
             | struct A {          std::string value;
             | explicit operator bool() const {             return
             | this->value.size();          }       };              // ...
             | A a {};       if (!a) {           // ...       }
        
               | fouric wrote:
               | "Not as weak as Java" is not a very interesting
               | benchmark, as Java _also_ has a poor type system. C++ 's
               | type system is pitiable relative to those of Rust,
               | Haskell, OCaml, and SML.
               | 
               | Moreover, in addition to being less expressive than them,
               | C++'s type system is also _weak_ , in formal sense, by
               | allowing many implicit type conversions - which is one of
               | the issues that I was complaining about. The fact that it
               | "has to be in place due to C not having a boolean type
               | until 1999" doesn't make it any less weak.
        
         | dylan604 wrote:
         | That so sounds like an error I would make and not some superDev
         | working at the Googs making around 4x the amount of money I
         | make.
        
           | myko wrote:
           | They're just people. If you want to get in you probably
           | could, with some effort.
        
           | anyfoo wrote:
           | Not sure why you think a "superDev" would be less susceptible
           | to simple typos?
        
         | [deleted]
        
         | shawnz wrote:
         | Other than this particular edge case it's not obvious to me why
         | bitwise operators shouldn't be applicable to boolean values.
         | Aren't they just single-bit vectors?
         | 
         | Of course it makes sense that logical operators wouldn't be
         | applicable to numeric types, but why the reverse?
        
           | phkahler wrote:
           | >> Other than this particular edge case it's not obvious to
           | me why bitwise operators shouldn't be applicable to boolean
           | values.
           | 
           | That is a really good question. At some point they decided
           | that true=1 and false=0 but I'm not sure how deep that goes.
           | In particular what does ! actually do in this context?
        
           | qalmakka wrote:
           | If you stop integer values from being implicitly convertible
           | to booleans, you break the language and its compatibility
           | with C.
           | 
           | The inverse is debatable, though. I honestly don't see why
           | someone would do bitwise operations on boolean, unless they
           | really wish to die a slow death from thousand cuts. Integer
           | promotion rules make even the simplest operations a wild
           | mess, and there's nothing in the standard that prevents bool
           | from having a sizeof equal to int (thus further complicating
           | everything).
           | 
           | It might be sensible for newer language revisions to consider
           | deprecating certain operators from being applied to bool,
           | given that there is a strong change that 99% of the time
           | their use is not on purpose, but I guess it depends on how
           | much disruptive such change would turn out to be.
        
             | shawnz wrote:
             | I don't think the other poster was imagining a language
             | that retained compatibility with C, but rather a new
             | language altogether. Of course it would be impossible to
             | change this aspect of the language if retaining
             | compatibility with C was a requirement.
             | 
             | > I honestly don't see why someone would do bitwise
             | operations on boolean
             | 
             | For example, you might _want_ the behaviour shown here of
             | not short-circuiting. Or you might want to create a bitwise
             | function that also allows calling on single-bit (i.e.
             | boolean) values.
        
         | gmfawcett wrote:
         | This is one of those times when, for all its verbosity, Ada got
         | it right. For boolean conjunction you must choose between
         | writing "A and B", or "A and then B". The "and then" version is
         | short circuiting, while the bare "and" version is not.
        
           | gene91 wrote:
           | This is a typo of missing an ampersand. If the author were
           | writing Ada, it would have been a typo of missing a "then".
           | How is it different?
        
           | shawnz wrote:
           | Visual Basic also has this distinction (but the keywords are
           | "And" and "AndAlso")
        
       | dolni wrote:
       | If you've been in tech for a while, this is one of those things
       | that makes you sigh and shake your fist at "move fast and break
       | stuff" as a strategy.
        
         | ipsum2 wrote:
         | Google's philosophy isn't "move fast and break stuff". It's
         | probably the opposite - "move slow and be careful". These
         | things happen.
        
         | throwntoday wrote:
         | That's more about challenging the status quo not bad project
         | management.
        
       | Animats wrote:
       | The reason this happened is that it wasn't followed by "Google
       | hit by 143 defective product lawsuits".
        
         | kevincox wrote:
         | I don't think they could possibly be sued for this. They would
         | just be responsible for fixing or refunding the product. In
         | this case they issued a "fix".
         | 
         | It is the same as when a car is defective. They don't get sued,
         | they do a recall and fix it.
        
       ___________________________________________________________________
       (page generated 2021-07-22 23:00 UTC)