Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
alandonovan opened this issue Dec 17, 2014 · 22 comments
Closed

Comments

@alandonovan
Copy link
Contributor

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.)

@alandonovan alandonovan added this to the Go1.5 milestone Dec 17, 2014
@slimsag
Copy link

slimsag commented Dec 17, 2014

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
Copy link

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
Copy link
Member

minux commented Dec 17, 2014

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
Copy link
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
Copy link
Contributor Author

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
Copy link
Member

minux commented Dec 17, 2014

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.)

@mattn
Copy link
Member

mattn commented Dec 18, 2014

@cookieo9
Copy link
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
Copy link

ghost commented Dec 19, 2014

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
Copy link
Member

minux commented Dec 19, 2014

I think this is a dup of #6011.

@011010101101
Copy link

@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.

@ghost
Copy link

ghost commented Mar 17, 2015

@BThomson, hmmm. Then I don't understand what @cookieo9 was suggesting would be better. It's generally good (for performance) to avoid branching, except that branching code is often more clear. In any case, I suspect it's moot because I can't think of an implementation of int() that wouldn't involve a branch somewhere under the hood. int() just hides the branch, and it is less clear... although the brevity is admirable.

@rsc rsc removed the repo-main label Apr 14, 2015
@bradfitz bradfitz modified the milestones: Unplanned, Go1.5 Jul 7, 2015
@bradfitz
Copy link
Contributor

bradfitz commented Jul 7, 2015

Removed Go 1.5. This is either a dup of #6011 or should go through the proposal process (write a doc) if this is actually a language change proposal.

@sirkon
Copy link

sirkon commented Sep 3, 2015

I hope they didn't/won't implement this. Implicit conversion is an evil whatever pratical reasons are listed.

@cespare
Copy link
Contributor

cespare commented Sep 3, 2015

@DenisCheremisov this proposal is for an explicit conversion.

@minux
Copy link
Member

minux commented Sep 3, 2015 via email

@griesemer griesemer changed the title spec: support int(bool) conversions in Go.1.5 proposal: support int(bool) conversions in Go.1.5 (language change) Sep 3, 2015
@adg
Copy link
Contributor

adg commented Sep 25, 2015

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.

@adg adg closed this as completed Sep 25, 2015
@golang golang locked and limited conversation to collaborators Sep 27, 2016
@ianlancetaylor ianlancetaylor removed their assignment May 4, 2021
@adonovan
Copy link
Member

adonovan commented Dec 15, 2023

@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
Copy link
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
Copy link
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
Copy link
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
Copy link
Member

adonovan commented Dec 20, 2023

@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 subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests