Skip to content

proposal: support int(bool) conversions in Go.1.5 (language change) #9367

Closed
@alandonovan

Description

@alandonovan

I propose the following language change for Go 1.5:

An explicit conversion int(b) where b has a boolean type would become legal, and would yield 1 if b is true, 0 otherwise.  Similar conversions would be legal for all numeric types.

Rationale: currently this function cannot be computed in a single expression, despite it being often useful, hard to misuse, efficiently implemented by modern ALUs, present in nearly all other languages, and syntactically natural in Go.

While I appreciate the value of avoiding implicit int/bool conversions, forbidding explicit ones seems slightly obtuse, and as a result of its omission, one must write four extra lines of code:

 var i int
 if b { 
     i = 1
 }
 ... i ...

which the gc compiler does not optimize this into the obvious single instruction.

The reverse operation bool(i), is not essential since i != 0 has the same effect and can be used in an expression context, but could be added for symmetry.  (I have no strong opinion.)

Activity

added this to the Go1.5 milestone on Dec 17, 2014
emidoots

emidoots commented on Dec 17, 2014

@emidoots

I'm no such authority to say, but I think things like this are best discussed on the golang-nuts mailing list first. Most people don't review each Go issue, in contrast most do read the mailing list and could provide useful insight before such a change is made.

ShawnMilo

ShawnMilo commented on Dec 17, 2014

@ShawnMilo

And on the list you'll be asked what problem this solves and how it solves it better than the existing method. And then they'll say that taking something completely unambiguous and impossible to misunderstand and adding the ability to do it in a redundant way which could be confusing and will cause bugs due to unintentional casting is not beneficial for the language. When it comes to Go, think minimalism.

If you have a use-case where your proposal is demonstrably better than the status quo, please provide it in the list for discussion, because without it the conversation will be a non-starter.

minux

minux commented on Dec 17, 2014

@minux
Member

I hate to say, but this has been proposed and rejected.

We should teach gc to generate better code, instead of adding features to
the language.

And yes, this should be discussed on golang-nuts first.

griesemer

griesemer commented on Dec 17, 2014

@griesemer
Contributor
  1. It shouldn't be too hard for a compiler to recognize
i := 0
if b {
   i = 1
}

and create the respective single instruction (or conditional bit set, depending on what happens with i, etc.)

  1. It's trivial to define e.g.
func bool2int(b bool) int {
   if b {
      return 1
   }
   return 0
} 

where needed.

  1. Together with 1), the bool2int function should become trivial code-wise and then should be inlineable, effectively giving you int(b).

  2. There may still be merit in conversions of bools to numeric values, but using a helper function for now should get you almost all the way there. The rest is optimization.

alandonovan

alandonovan commented on Dec 17, 2014

@alandonovan
ContributorAuthor

On 17 December 2014 at 14:38, Robert Griesemer notifications@github.com
wrote:

  1. It shouldn't be too hard for a compiler to recognize

i := 0
if b {
i = 1
}

and create the respective single instruction (or conditional bit set,
depending on what happens with i, etc.)

  1. It's trivial to define e.g.

func bool2int(b bool) int {
if b {
return 1
}
return 0
}

where needed.

  1. Together with 1), the bool2int function should become trivial code-wise
    and then should be inlineable, effectively giving you int(b).

  2. There may still be merit in conversions of bools to numeric values, but
    using a helper function for now should get you almost all the way there.
    The rest is optimization.

The question is: would you prefer to read just this "int(x.f > 0)", or four
lines of statements inconveniently breaking up a long expression?
My assertion is that the status quo is both less readable and less
efficient.

minux

minux commented on Dec 17, 2014

@minux
Member

i think bool2int(x.f > 0) is just as readable.
if we really need to change the language, ternary operator is more general than this proposal,
and it's also trivial for the compiler to turn that into a conditional select instruction.
(I'm not proposing ternary operators... it's too ugly when nested.)

cookieo9

cookieo9 commented on Dec 18, 2014

@cookieo9
Contributor

In my experience the most beneficial of this feature would be as follows:

var check bool = something
// ...
value := requiredValue + int(check) * optionalValue

IE: only add optionalValue if check is true.

This would normally be expressed in go as:

var check bool = something
// ...
value := requiredValue
if check {
    value += optionalValue
}

In this situation I would argue that the later is more clear about what is happening. Also, the former would most likely require a multiplication instead the conditional branch. Only in the case where optionalValue == 1 or -1 (ie: add or subtract 1 if boolean is set) could the multiplication be easily avoided.

If it is the case that

value := required + int(check)

would produce better code than

value := required
if check {
    value++
}

then the optimizer should be improved. IMHO the latter is still clearer about what is happening, albeit not as much as the original example.

ghost

ghost commented on Dec 19, 2014

@ghost

Also, the former would most likely require a multiplication instead the conditional branch.
Only in the case where optionalValue == 1 or -1 (ie: add or subtract 1 if boolean is set)
could the multiplication be easily avoided.

It's been a couple of decades since a paid attention to CPU architecture, but at that time conditional branching was significantly more expensive than multiplication. Have things changed that much?

minux

minux commented on Dec 19, 2014

@minux
Member

I think this is a dup of #6011.

011010101101

011010101101 commented on Mar 17, 2015

@011010101101

@serussell No, branching is still more expensive. Modern CPUs have to guess which way a branch is going to go. If they guess wrong, they will realize much later that they have to go back and redo a lot of prior computation. That is very slow: something like 20 instructions wasted on a modern Intel CPU. See https://en.wikipedia.org/wiki/Branch_predictor

For speed, then, it would be better for the compilers to avoid conditional jumps for bool-to-int conversion.

6 remaining items

cespare

cespare commented on Sep 3, 2015

@cespare
Contributor

@DenisCheremisov this proposal is for an explicit conversion.

minux

minux commented on Sep 3, 2015

@minux
Member
changed the title [-]spec: support int(bool) conversions in Go.1.5[/-] [+]proposal: support int(bool) conversions in Go.1.5 (language change)[/+] on Sep 3, 2015
adg

adg commented on Sep 25, 2015

@adg
Contributor

The thread on golang-nuts raises a couple of key issues with this proposal:

  • It is yet another very small convenience that can be replaced with a short function,
  • It's not clear whether bool(0) should return false or true. There are arguments both ways.

For these reasons I am going to decline this proposal.

locked and limited conversation to collaborators on Sep 27, 2016
removed their assignment
on May 4, 2021
adonovan

adonovan commented on Dec 15, 2023

@adonovan
Member

@rsc and I were chatting about this earlier in the week and he suggested gathering some data, so I did. See https://go.dev/cl/550235 for the logic and its complete output.

In short, across about 19,000 modules, there are about 10K places where an if/else statement is used to simulate an int(bool) conversion. (I didn't attempt to find places where if/else was used to compute bool < bool, as is common in sort.Interface.Less implementations.) Of those, I ignored the ~5.5K in generated .pb.go files, and the ~2K in tensorflow generic_cmp files, leaving about 2700 more interesting cases. Here's a random sample of 100:

https://go-mod-viewer.appspot.com/github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/atomicbitops/bool.go#L34: [if]: u = int(val)
https://go-mod-viewer.appspot.com/github.com/Hyperledger-TWGC/tjfoc-gm@v1.4.0/sm4/sm4_gcm.go#L77: [return]: return int(temp&0x01 == 1)
https://go-mod-viewer.appspot.com/github.com/Hyperledger-TWGC/tjfoc-gm@v1.4.0/sm4/sm4_gcm.go#L77: [return]: return int(temp&0x01 == 1)
https://go-mod-viewer.appspot.com/github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/xproto/xproto.go#L10719: [if-else]: buf[b] = int(OwnerEvents)
https://go-mod-viewer.appspot.com/github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/xproto/xproto.go#L10719: [if-else]: buf[b] = int(OwnerEvents)
https://go-mod-viewer.appspot.com/github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/randr/randr.go#L3804: [if-else]: buf[b] = int(Pending)
https://go-mod-viewer.appspot.com/github.com/m3db/m3@v1.5.0/src/dbnode/storage/bootstrap_instrumentation.go#L180: [if]: status = int(isBootstrapped)
https://go-mod-viewer.appspot.com/github.com/m3db/m3@v1.5.0/src/dbnode/storage/bootstrap_instrumentation.go#L180: [if]: status = int(isBootstrapped)
https://go-mod-viewer.appspot.com/github.com/BurntSushi/xgb@v0.0.0-20210121224620-deaf085860bc/randr/randr.go#L3797: [if-else]: buf[b] = int(Delete)
https://go-mod-viewer.appspot.com/github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/shape/shape.go#L130: [if-else]: buf[b] = int(v.Shaped)
https://go-mod-viewer.appspot.com/github.com/apache/arrow/go/v13@v13.0.0/arrow/compute/internal/exec/span.go#L280: [if-else]: a.Nulls = int(val.IsValid())
https://go-mod-viewer.appspot.com/github.com/gagliardetto/binary@v0.7.9/encoder.go#L189: [if]: num = int(b)
https://go-mod-viewer.appspot.com/github.com/gagliardetto/binary@v0.7.9/encoder.go#L189: [if]: num = int(b)
https://go-mod-viewer.appspot.com/gopkg.in/olebedev/go-duktape.v1@v1.0.0-20151008052556-e2ae92f01e4a/api.go#L947: [if]: val = int(val)
https://go-mod-viewer.appspot.com/gopkg.in/olebedev/go-duktape.v1@v1.0.0-20151008052556-e2ae92f01e4a/api.go#L947: [if]: val = int(val)
https://go-mod-viewer.appspot.com/github.com/btccom/go-micro/v2@v2.9.3/api/router/static/static.go#L232: [if]: idx = int(len(req.URL.Path) > 0 && req.URL.Path != "/")
https://go-mod-viewer.appspot.com/github.com/pion/webrtc/v3@v3.2.24/atomicbool.go#L27: [if]: i = int(value)
https://go-mod-viewer.appspot.com/github.com/pion/webrtc/v3@v3.2.24/atomicbool.go#L27: [if]: i = int(value)
https://go-mod-viewer.appspot.com/github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/glx/glx.go#L1494: [if-else]: buf[b] = int(IsDirect)
https://go-mod-viewer.appspot.com/github.com/thanos-io/thanos@v0.32.5/pkg/store/cache/caching_bucket_test.go#L442: [if]: expectedHitsDiff = int(expectedCache)
https://go-mod-viewer.appspot.com/github.com/apache/arrow/go/v14@v14.0.1/internal/bitutils/bitmap_generate.go#L85: [if-else]: outResults[i] = int(g())
https://go-mod-viewer.appspot.com/github.com/jezek/xgb@v1.1.1/xprint/xprint.go#L639: [if-else]: buf[b] = int(Cancel)
https://go-mod-viewer.appspot.com/go.flow.arcalot.io/pluginsdk@v0.7.0/schema/function.go#L322: [if]: expectedReturnVals = int(f.StaticOutputValue != nil || f.DynamicTypeHandler != nil)
https://go-mod-viewer.appspot.com/github.com/peske/x-tools@v0.0.0-20221212040959-717b025fabf0/cmd/goyacc/yacc.go#L2126: [if]: nolook = int(tystate[i] != MUSTLOOKAHEAD)
https://go-mod-viewer.appspot.com/github.com/pocketbase/pocketbase@v0.20.0/forms/admin_upsert_test.go#L160: [if]: expectInterceptorCall = int(s.expectError)
https://go-mod-viewer.appspot.com/go.starlark.net@v0.0.0-20231101134539-556fd59b42f6/internal/compile/serial.go#L207: [return]: return int(b)
https://go-mod-viewer.appspot.com/go.starlark.net@v0.0.0-20231101134539-556fd59b42f6/internal/compile/serial.go#L207: [return]: return int(b)
https://go-mod-viewer.appspot.com/github.com/shakinm/xlsReader@v0.9.12/xls/workbook.go#L107: [if-else]: grbitOffset = int(len(wb.sst.RgbSrc) == 0)
https://go-mod-viewer.appspot.com/github.com/shakinm/xlsReader@v0.9.12/xls/workbook.go#L107: [if-else]: grbitOffset = int(len(wb.sst.RgbSrc) == 0)
https://go-mod-viewer.appspot.com/github.com/BurntSushi/xgb@v0.0.0-20210121224620-deaf085860bc/xproto/xproto.go#L10065: [if-else]: buf[b] = int(Delete)
https://go-mod-viewer.appspot.com/github.com/BurntSushi/xgb@v0.0.0-20210121224620-deaf085860bc/xproto/xproto.go#L10065: [if-else]: buf[b] = int(Delete)
https://go-mod-viewer.appspot.com/github.com/dop251/goja@v0.0.0-20231027120936-b396bb4c349d/ftoa/ftoa.go#L614: [if]: stop = int(len(buf) > 0 && buf[0] == '-')
https://go-mod-viewer.appspot.com/github.com/dop251/goja@v0.0.0-20231027120936-b396bb4c349d/ftoa/ftoa.go#L614: [if]: stop = int(len(buf) > 0 && buf[0] == '-')
https://go-mod-viewer.appspot.com/go.etcd.io/raft/v3@v3.0.0-20231213110755-8757de38ed2c/rawnode_test.go#L325: [if]: maybePlusOne = int(ok && autoLeave)
https://go-mod-viewer.appspot.com/github.com/XiaoMi/Gaea@v1.2.5/mysql/resultset_sort.go#L132: [return]: return int(v > s)
https://go-mod-viewer.appspot.com/github.com/XiaoMi/Gaea@v1.2.5/mysql/resultset_sort.go#L132: [return]: return int(v > s)
https://go-mod-viewer.appspot.com/github.com/dotcloud/go-redis-server@v0.0.0-20130830204822-e4d48d56d178/auto.go#L174: [if]: start = int(mtype.NumIn() > 0 && mtype.In(0).AssignableTo(reflect.TypeOf(autoHandler)))
https://go-mod-viewer.appspot.com/github.com/dotcloud/go-redis-server@v0.0.0-20130830204822-e4d48d56d178/auto.go#L174: [if]: start = int(mtype.NumIn() > 0 && mtype.In(0).AssignableTo(reflect.TypeOf(autoHandler)))
https://go-mod-viewer.appspot.com/github.com/andybalholm/brotli@v1.0.6/brotli_bit_stream.go#L306: [if-else]: tmp = int(depths[symbols[0]] == 1)
https://go-mod-viewer.appspot.com/github.com/andybalholm/brotli@v1.0.6/brotli_bit_stream.go#L306: [if-else]: tmp = int(depths[symbols[0]] == 1)
https://go-mod-viewer.appspot.com/github.com/mitchellh/go-vnc@v0.0.0-20150629162542-723ed9867aed/pixel_format.go#L111: [if-else]: boolByte = int(format.TrueColor)
https://go-mod-viewer.appspot.com/github.com/mitchellh/go-vnc@v0.0.0-20150629162542-723ed9867aed/pixel_format.go#L111: [if-else]: boolByte = int(format.TrueColor)
https://go-mod-viewer.appspot.com/github.com/la5nta/wl2k-go@v0.11.8/rigcontrol/hamlib/rigctld.go#L168: [if]: bInt = int(on == true)
https://go-mod-viewer.appspot.com/github.com/segmentio/parquet-go@v0.0.0-20230712180008-5d42db8f0d47/file.go#L692: [if]: f.index = int(f.dictOffset > 0)
https://go-mod-viewer.appspot.com/github.com/segmentio/parquet-go@v0.0.0-20230712180008-5d42db8f0d47/file.go#L692: [if]: f.index = int(f.dictOffset > 0)
https://go-mod-viewer.appspot.com/github.com/andybalholm/brotli@v1.0.6/decode.go#L1282: [if-else]: s.should_wrap_ringbuffer = int(uint(s.pos) != 0)
https://go-mod-viewer.appspot.com/github.com/andybalholm/brotli@v1.0.6/decode.go#L1282: [if-else]: s.should_wrap_ringbuffer = int(uint(s.pos) != 0)
https://go-mod-viewer.appspot.com/github.com/regen-network/regen-ledger/api@v1.1.0/regen/ecocredit/v1alpha1/types.pulsar.go#L2460: [if-else]: dAtA[i] = int(x.AllowlistEnabled)
https://go-mod-viewer.appspot.com/github.com/intel/goresctrl@v0.5.0/pkg/sst/sst_if.go#L109: [if]: ReadWrite = int(doWrite)
https://go-mod-viewer.appspot.com/github.com/intel/goresctrl@v0.5.0/pkg/blockio/oci_test.go#L95: [if]: expectedErrorCount = int(len(tc.expectedErrorSubstrings) > 0)
https://go-mod-viewer.appspot.com/cosmossdk.io/client/v2@v2.0.0-beta.1/internal/testpb/query.pulsar.go#L2731: [if-else]: dAtA[i] = int(x.Bools[iNdEx])
https://go-mod-viewer.appspot.com/github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/xproto/xproto.go#L7614: [if-else]: buf[b] = int(Exposures)
https://go-mod-viewer.appspot.com/github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/xproto/xproto.go#L7614: [if-else]: buf[b] = int(Exposures)
https://go-mod-viewer.appspot.com/github.com/jezek/xgb@v1.1.1/xproto/xproto.go#L7364: [if-else]: buf[b] = int(DoAcceleration)
https://go-mod-viewer.appspot.com/github.com/jezek/xgb@v1.1.1/xproto/xproto.go#L7364: [if-else]: buf[b] = int(DoAcceleration)
https://go-mod-viewer.appspot.com/github.com/aviddiviner/docopt-go@v0.0.0-20170807220726-d8a1d67efc6a/docopt.go#L433: [if]: argcount = int(eq == "=")
https://go-mod-viewer.appspot.com/github.com/aviddiviner/docopt-go@v0.0.0-20170807220726-d8a1d67efc6a/docopt.go#L433: [if]: argcount = int(eq == "=")
https://go-mod-viewer.appspot.com/github.com/dubbogo/gost@v1.14.0/time/timer.go#L118: [if-else]: ret = int(first.trig > second.trig)
https://go-mod-viewer.appspot.com/github.com/dubbogo/gost@v1.14.0/time/timer.go#L118: [if-else]: ret = int(first.trig > second.trig)
https://go-mod-viewer.appspot.com/github.com/oasisprotocol/ed25519@v0.0.0-20210505154701-76d8c688d86e/internal/modm/modm_64bit.go#L736: [if]: cmp = int(i == 0)
https://go-mod-viewer.appspot.com/bosun.org@v0.0.0-20210513094433-e25bc3e69a1f/cmd/scollector/collectors/ntp_unix.go#L76: [if]: current_source = int(fl == "")
https://go-mod-viewer.appspot.com/bosun.org@v0.0.0-20210513094433-e25bc3e69a1f/cmd/scollector/collectors/ntp_unix.go#L76: [if]: current_source = int(fl == "
")
https://go-mod-viewer.appspot.com/github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/state/wire/wire.go#L88: [if-else]: v = int(b)
https://go-mod-viewer.appspot.com/github.com/hyperledger/fabric-amcl@v0.0.0-20230602173724-9e02669dceb2/core/FP256BN/FP4.go#L214: [if-else]: u = int(F.a.iszilch())
https://go-mod-viewer.appspot.com/github.com/consensys/gnark-crypto@v0.12.1/ecc/bw6-761/fr/fri/fri.go#L309: [if-else]: fullMerkleProof = int(len(pp.Rounds[0].Interactions[0][0].ProofSet) > len(pp.Rounds[0].Interactions[0][1].ProofSet))
https://go-mod-viewer.appspot.com/github.com/consensys/gnark-crypto@v0.12.1/ecc/bw6-761/fr/fri/fri.go#L309: [if-else]: fullMerkleProof = int(len(pp.Rounds[0].Interactions[0][0].ProofSet) > len(pp.Rounds[0].Interactions[0][1].ProofSet))
https://go-mod-viewer.appspot.com/github.com/onosproject/onos-api/go@v0.10.32/onos/config/v3/typedvalue.go#L877: [if]: intval = int(b)
https://go-mod-viewer.appspot.com/github.com/onosproject/onos-api/go@v0.10.32/onos/config/v3/typedvalue.go#L877: [if]: intval = int(b)
https://go-mod-viewer.appspot.com/github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/sstable/writer_test.go#L923: [if]: expectedLength = int(expectedIntersects)
https://go-mod-viewer.appspot.com/github.com/golang-commonmark/markdown@v0.0.0-20180910011815-a8f139058164/blockquote.go#L160: [if]: d = int(spaceAfterMarker)
https://go-mod-viewer.appspot.com/github.com/golang-commonmark/markdown@v0.0.0-20180910011815-a8f139058164/blockquote.go#L160: [if]: d = int(spaceAfterMarker)
https://go-mod-viewer.appspot.com/github.com/m3db/m3@v1.5.0/src/dbnode/persist/fs/msgpack/stream.go#L170: [if]: unreadBytes = int(s.unreadByte != -1)
https://go-mod-viewer.appspot.com/github.com/m3db/m3@v1.5.0/src/dbnode/persist/fs/msgpack/stream.go#L170: [if]: unreadBytes = int(s.unreadByte != -1)
https://go-mod-viewer.appspot.com/github.com/regen-network/regen-ledger/api@v1.1.0/regen/ecocredit/marketplace/v1/tx.pulsar.go#L2785: [if-else]: dAtA[i] = int(x.DisableAutoRetire)
https://go-mod-viewer.appspot.com/github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/datacodec/boolean.go#L187: [if-else]: *d = int(wasNull || !val)
https://go-mod-viewer.appspot.com/github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/datacodec/boolean.go#L187: [if-else]: *d = int(wasNull || !val)
https://go-mod-viewer.appspot.com/github.com/BurntSushi/xgb@v0.0.0-20210121224620-deaf085860bc/xproto/xproto.go#L3668: [if-else]: buf[b] = int(v.OverrideRedirect)
https://go-mod-viewer.appspot.com/github.com/BurntSushi/xgb@v0.0.0-20210121224620-deaf085860bc/xproto/xproto.go#L3668: [if-else]: buf[b] = int(v.OverrideRedirect)
https://go-mod-viewer.appspot.com/github.com/zhangzhaojian/go-mongodb@v1.1.0/mongo/collection.go#L388: [if]: limit = int(deleteOne)
https://go-mod-viewer.appspot.com/github.com/zhangzhaojian/go-mongodb@v1.1.0/mongo/collection.go#L388: [if]: limit = int(deleteOne)
https://go-mod-viewer.appspot.com/github.com/sajari/fuzzy@v1.0.0/fuzzy.go#L255: [if-else]: temp = int((*a)[j-1] == (*b)[i-1])
https://go-mod-viewer.appspot.com/github.com/sajari/fuzzy@v1.0.0/fuzzy.go#L255: [if-else]: temp = int((*a)[j-1] == (*b)[i-1])
https://go-mod-viewer.appspot.com/github.com/coreservice-io/utils@v0.3.0/version_util/version.go#L81: [return]: return int(a.tail > b.tail)
https://go-mod-viewer.appspot.com/github.com/coreservice-io/utils@v0.3.0/version_util/version.go#L81: [return]: return int(a.tail > b.tail)
https://go-mod-viewer.appspot.com/github.com/uadmin/uadmin@v0.10.1/setting.go#L522: [if]: n = int(v)
https://go-mod-viewer.appspot.com/github.com/uadmin/uadmin@v0.10.1/setting.go#L522: [if]: n = int(v)
https://go-mod-viewer.appspot.com/github.com/fraugster/parquet-go@v0.12.0/type_boolean.go#L91: [if]: v = int(values[i].(bool))
https://go-mod-viewer.appspot.com/github.com/fraugster/parquet-go@v0.12.0/type_boolean.go#L91: [if]: v = int(values[i].(bool))
https://go-mod-viewer.appspot.com/github.com/BurntSushi/xgb@v0.0.0-20210121224620-deaf085860bc/xproto/xproto.go#L10719: [if-else]: buf[b] = int(OwnerEvents)
https://go-mod-viewer.appspot.com/github.com/BurntSushi/xgb@v0.0.0-20210121224620-deaf085860bc/xproto/xproto.go#L10719: [if-else]: buf[b] = int(OwnerEvents)
https://go-mod-viewer.appspot.com/github.com/blevesearch/geo@v0.1.18/s2/edge_clipping.go#L148: [if]: ai = int(a.X > b.X)
https://go-mod-viewer.appspot.com/github.com/blevesearch/geo@v0.1.18/s2/edge_clipping.go#L148: [if]: ai = int(a.X > b.X)
https://go-mod-viewer.appspot.com/github.com/polarismesh/polaris@v1.17.8/store/mysql/strategy.go#L80: [if]: isDefault = int(strategy.Default)
https://go-mod-viewer.appspot.com/github.com/polarismesh/polaris@v1.17.8/store/mysql/strategy.go#L80: [if]: isDefault = int(strategy.Default)
https://go-mod-viewer.appspot.com/github.com/cosmos/cosmos-proto@v1.0.0-beta.3/internal/testprotos/test3/test.pulsar.go#L6416: [if-else]: dAtA[i] = int(x.RepeatedBool[iNdEx])
https://go-mod-viewer.appspot.com/github.com/cosmos/cosmos-proto@v1.0.0-beta.3/internal/testprotos/test3/test.pulsar.go#L6416: [if-else]: dAtA[i] = int(x.RepeatedBool[iNdEx])
https://go-mod-viewer.appspot.com/github.com/u2takey/go-utils@v0.3.1/strings/string.go#L225: [if]: i = int(strings.Index(str, \u) > 0)
https://go-mod-viewer.appspot.com/github.com/u2takey/go-utils@v0.3.1/strings/string.go#L225: [if]: i = int(strings.Index(str, \u) > 0)
https://go-mod-viewer.appspot.com/github.com/regen-network/regen-ledger/api/v2@v2.3.0/regen/ecocredit/marketplace/v1/state.pulsar.go#L515: [if-else]: dAtA[i] = int(x.Maker)
https://go-mod-viewer.appspot.com/github.com/parquet-go/parquet-go@v0.20.0/row_buffer_test.go#L146: [if]: definitionLevel = int(!node.Required())

adonovan

adonovan commented on Dec 15, 2023

@adonovan
Member

Given the adjacent dups in the above, seems like the measurement system runs every package twice (perhaps p and p_test?). The boolconv.txt file shrinks by 35% upon sorting, so scale my above figures by that amount too.

adonovan

adonovan commented on Dec 20, 2023

@adonovan
Member

Findings in std:

src/runtime/proc.go:5422:2: [if]: run0 = int(!iscgo && cgoHasExtraM && extraMLength.Load() > 0)
src/runtime/symtab.go:1062:2: [if]: mask = int(off == ^uint32(0))
src/reflect/abi.go:380:3: [if]: x = int(b.Get(i))
src/time/format.go:417:2: [if]: n = int(u == 0)
src/compress/flate/huffman_bit_writer.go:405:2: [if]: flag = int(isEof)
src/encoding/binary/binary.go:348:4: [if-else]: bs[0] = int(*v)
src/encoding/binary/binary.go:354:4: [if-else]: bs[0] = int(v)
src/encoding/binary/binary.go:361:5: [if-else]: bs[i] = int(x)
src/encoding/binary/binary.go:546:2: [if-else]: e.buf[e.offset] = int(x)
src/math/big/float.go:1377:2: [if]: sbit = int(len(r) > 0)
src/math/big/nat.go:235:3: [if-else]: c = int(cx < c2 || cy < c3)
src/crypto/x509/pkcs1.go:108:2: [if]: version = int(len(key.Primes) > 2)
src/internal/zstd/zstd.go:210:2: [if-else]: windowDescriptorSize = int(singleSegment)
src/go/printer/nodes.go:619:5: [if]: min = int(prev != nil && name == prev)
src/go/types/mono.go:198:3: [if]: weight = int(typ == targ)
src/internal/pkgbits/encoder.go:275:2: [if]: x = int(b)
src/compress/flate/deflate_test.go:180:3: [if-else]: b[i] = int(r.cur+int64(i) >= r.l-1<<16)
src/go/scanner/scanner_test.go:735:2: [if]: cnt = int(err != "")
src/go/types/hilbert_test.go:153:4: [if]: v = int(i == j)
src/strings/builder_test.go:105:3: [if]: wantAllocs = int(growLen == 0)
src/unicode/utf8/utf8_test.go:168:3: [if]: wantsize = int(wantsize >= len(b))
jimmyfrasche

jimmyfrasche commented on Dec 20, 2023

@jimmyfrasche
Member

@adonovan should this issue be reopened?

It looks like this pattern did not get detected: https://cs.opensource.google/go/go/+/refs/tags/go1.21.5:src/sync/atomic/type.go;l=31 (which is then called 4 times in the lines above it)

adonovan

adonovan commented on Dec 20, 2023

@adonovan
Member

@adonovan should this issue be reopened?

Russ suggested I create a new issue summarizing all previous discoveries. I'll do that presently. [Done: #64825]

It looks like this pattern did not get detected: https://cs.opensource.google/go/go/+/refs/tags/go1.21.5:src/sync/atomic/type.go;l=31 (which is then called 4 times in the lines above it)

Yeah, the pattern matcher for if cond { x = 1 } has both if-only and if-else forms; the matcher for return statements should do the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @bradfitz@mattn@sirkon@rsc@cookieo9

        Issue actions

          proposal: support int(bool) conversions in Go.1.5 (language change) · Issue #9367 · golang/go