kandi background
kandi background
Explore Kits
kandi background
Explore Kits
Go is a static, compiled language created by Google. Go has advanced memory safety, garbage collection, structural typing, and CSP-style concurrency. Presently, Go is the favorite language of young developers.

Popular New Releases in Go

Kubernetes v1.24.0-rc.0

v20.10.12

v0.97.3

Release v1.7.7

v0.41.0

kubernetes

Kubernetes v1.24.0-rc.0

moby

v20.10.12

hugo

v0.97.3

gin

Release v1.7.7

frp

v0.41.0

Popular Libraries in Go

go

by golang go

star image 97672 NOASSERTION

The Go programming language

kubernetes

by kubernetes go

star image 87661 Apache-2.0

Production-Grade Container Scheduling and Management

awesome-go

by avelino go

star image 76582 MIT

A curated list of awesome Go frameworks, libraries and software

moby

by moby go

star image 62382 Apache-2.0

Moby Project - a collaborative project for the container ecosystem to assemble container-based systems

hugo

by gohugoio go

star image 58416 Apache-2.0

The world’s fastest framework for building websites.

gin

by gin-gonic go

star image 56154 MIT

Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.

frp

by fatedier go

star image 55464 Apache-2.0

A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet.

syncthing

by syncthing go

star image 44131 MPL-2.0

Open Source Continuous File Synchronization

fzf

by junegunn go

star image 43649 MIT

:cherry_blossom: A command-line fuzzy finder

go

by golang go

star image 97672 NOASSERTION

The Go programming language

kubernetes

by kubernetes go

star image 87661 Apache-2.0

Production-Grade Container Scheduling and Management

awesome-go

by avelino go

star image 76582 MIT

A curated list of awesome Go frameworks, libraries and software

moby

by moby go

star image 62382 Apache-2.0

Moby Project - a collaborative project for the container ecosystem to assemble container-based systems

hugo

by gohugoio go

star image 58416 Apache-2.0

The world’s fastest framework for building websites.

gin

by gin-gonic go

star image 56154 MIT

Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.

frp

by fatedier go

star image 55464 Apache-2.0

A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet.

syncthing

by syncthing go

star image 44131 MPL-2.0

Open Source Continuous File Synchronization

fzf

by junegunn go

star image 43649 MIT

:cherry_blossom: A command-line fuzzy finder

Trending New libraries in Go

fiber

by gofiber go

star image 19407 MIT

⚡️ Express inspired web framework written in Go

go-zero

by zeromicro go

star image 16273 MIT

A web and RPC framework written in Go. It's born to ensure the stability of the busy sites with resilient design. Builtin goctl greatly improves the development productivity.

algorithm-pattern

by greyireland go

star image 12016

算法模板,最科学的刷题方式,最快速的刷题路径,你值得拥有~

go-zero

by tal-tech go

star image 10720 MIT

go-zero is a web and rpc framework written in Go. It's born to ensure the stability of the busy sites with resilient design. Builtin goctl greatly improves the development productivity.

bubbletea

by charmbracelet go

star image 9726 MIT

A powerful little TUI framework 🏗

duf

by muesli go

star image 8271 NOASSERTION

Disk Usage/Free Utility - a better 'df' alternative

Xray-core

by XTLS go

star image 8099 MPL-2.0

Xray, Penetrates Everything. Also the best v2ray-core, with XTLS support. Fully compatible configuration.

nuclei

by projectdiscovery go

star image 7947 MIT

Fast and customizable vulnerability scanner based on simple YAML based DSL.

lima

by lima-vm go

star image 7768 Apache-2.0

Linux virtual machines, typically on macOS, for running containerd

fiber

by gofiber go

star image 19407 MIT

⚡️ Express inspired web framework written in Go

go-zero

by zeromicro go

star image 16273 MIT

A web and RPC framework written in Go. It's born to ensure the stability of the busy sites with resilient design. Builtin goctl greatly improves the development productivity.

algorithm-pattern

by greyireland go

star image 12016

算法模板,最科学的刷题方式,最快速的刷题路径,你值得拥有~

go-zero

by tal-tech go

star image 10720 MIT

go-zero is a web and rpc framework written in Go. It's born to ensure the stability of the busy sites with resilient design. Builtin goctl greatly improves the development productivity.

bubbletea

by charmbracelet go

star image 9726 MIT

A powerful little TUI framework 🏗

duf

by muesli go

star image 8271 NOASSERTION

Disk Usage/Free Utility - a better 'df' alternative

Xray-core

by XTLS go

star image 8099 MPL-2.0

Xray, Penetrates Everything. Also the best v2ray-core, with XTLS support. Fully compatible configuration.

nuclei

by projectdiscovery go

star image 7947 MIT

Fast and customizable vulnerability scanner based on simple YAML based DSL.

lima

by lima-vm go

star image 7768 Apache-2.0

Linux virtual machines, typically on macOS, for running containerd

Top Authors in Go

1

321 Libraries

21651

2

316 Libraries

0

3

268 Libraries

183422

4

235 Libraries

180804

5

233 Libraries

18842

6

212 Libraries

7560

7

198 Libraries

2566

8

195 Libraries

0

9

188 Libraries

1559

10

159 Libraries

13

1

321 Libraries

21651

2

316 Libraries

0

3

268 Libraries

183422

4

235 Libraries

180804

5

233 Libraries

18842

6

212 Libraries

7560

7

198 Libraries

2566

8

195 Libraries

0

9

188 Libraries

1559

10

159 Libraries

13

Trending Kits in Go

Go is a programming language that makes it easy to build simple, reliable, and efficient software. Go is a programming language developed by Google in 2009. In recent years, it has gained popularity among developers due to its easy-to-learn and use syntax and the fact that it is an open source language. Go has been used for building server applications, websites, games and also mobile apps. There are many free Go coding assessment libraries available for developers to use. These libraries help in improving the performance of the application and make it more user friendly. Go can be used to create high performing applications that are easy to maintain. Some of the most popular Go Coding Assessment Open Source libraries among developers are: kube-scan - kubescan: Octarine k8s cluster risk assessment tool; recursebuster - rapid content discovery tool for recursively querying webservers; paf-credentials-checker - high performing offline tool to easily assess.

Go is a programming language that makes it easy to build simple, reliable, and efficient software. Go is a programming language developed by Google in 2009. In recent years, it has gained popularity among developers due to its easy-to-learn and use syntax and the fact that it is an open source language. Go has been used for building server applications, websites, games and also mobile apps. There are many free Go coding assessment libraries available for developers to use. These libraries help in improving the performance of the application and make it more user friendly. Go can be used to create high performing applications that are easy to maintain. Some of the most popular Go Coding Assessment Open Source libraries among developers are: kube-scan - kubescan: Octarine k8s cluster risk assessment tool; recursebuster - rapid content discovery tool for recursively querying webservers; paf-credentials-checker - high performing offline tool to easily assess.

Trending Discussions on Go

    Why is Rust NLL not working for multiple borrows in the same statement?
    Docker push to AWS ECR hangs immediately and times out
    How does Java know which overloaded method to call with lambda expressions? (Supplier, Consumer, Callable, ...)
    pip-compile raising AssertionError on its logging handler
    Is if(A | B) always faster than if(A || B)?
    What is the proper evaluation order when assigning a value in a map?
    Unable to specify `edition2021` in order to use unstable packages in Rust
    Android Studio strange code sub-windows after upgrade to Arctic Fox (2020.3.1)
    ellipsis ... as function in substitute?
    Python 3.10 pattern matching (PEP 634) - wildcard in string

QUESTION

Why is Rust NLL not working for multiple borrows in the same statement?

Asked 2022-Apr-12 at 00:43

First, I tried something like this:

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3

It can't be compiled because:

error[E0502]: cannot borrow `vec` as immutable because it is also borrowed as mutable

I thought that the Rust borrow checker could be smarter than this, so I found something called NLL, and it should solve this problem.

I tried the sample:

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5

It could work, but why is it not working with rotate_right? Both of them take a &mut self. What's going on?

ANSWER

Answered 2022-Apr-12 at 00:43

It is definitely an interesting one.

They are similar - but not quite the same. resize() is a member of Vec. rotate_right(), on the other hand, is a method of slices.

Vec<T> derefs to [T], so most of the time this does not matter. But actually, while this call:

copy icondownload icon

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6

Desugars to something like:

copy icondownload icon

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7

This call:

copy icondownload icon

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7vec.rotate_right(vec.len());
8

Is more like:

copy icondownload icon

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7vec.rotate_right(vec.len());
8&lt;[i32]&gt;::rotate_right(
9    &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(&amp;mut vec),
10    &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec),
11);
12

But in what order?

This is the MIR for rotate_right() (simplified a lot):

copy icondownload icon

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7vec.rotate_right(vec.len());
8&lt;[i32]&gt;::rotate_right(
9    &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(&amp;mut vec),
10    &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec),
11);
12fn foo() -&gt; () {
13    _4 = &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(move _5);
14    _6 = Vec::&lt;i32&gt;::len(move _7);
15    _2 = core::slice::&lt;impl [i32]&gt;::rotate_right(move _3, move _6);
16}
17

And this is the MIR for resize() (again, simplified a lot):

copy icondownload icon

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7vec.rotate_right(vec.len());
8&lt;[i32]&gt;::rotate_right(
9    &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(&amp;mut vec),
10    &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec),
11);
12fn foo() -&gt; () {
13    _4 = &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(move _5);
14    _6 = Vec::&lt;i32&gt;::len(move _7);
15    _2 = core::slice::&lt;impl [i32]&gt;::rotate_right(move _3, move _6);
16}
17fn foo() -&gt; () {
18    _4 = Vec::&lt;i32&gt;::len(move _5);
19    _2 = Vec::&lt;i32&gt;::resize(move _3, move _4, const 0_i32);
20}
21

In the resize() example, we first call Vec::len() with a reference to vec. This returns usize. Then we call Vec::resize(), when we have no outstanding references to vec, so mutably borrowing it is fine!

However, with rotate_right(), first we call <Vec<i32> as DerefMut>::deref_mut(&mut vec). This returns &mut [i32], with its lifetime tied to vec. That is, as long as this reference (mutable reference!) is alive, we are not allowed to use have any other reference to vec. But then we try to borrow vec in order to pass the (shared, but it doesn't matter) reference to Vec::len(), while we still need to use the mutable reference from deref_mut() later, in the call to <[i32]>::rotate_right()! This is an error.

This is because Rust defines an evaluation order for operands:

Expressions taking multiple operands are evaluated left to right as written in the source code.

Because vec.resize() is actually (&mut *vec).rotate_right(), we first evaluate the dereference+reference, then the arguments:

copy icondownload icon

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7vec.rotate_right(vec.len());
8&lt;[i32]&gt;::rotate_right(
9    &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(&amp;mut vec),
10    &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec),
11);
12fn foo() -&gt; () {
13    _4 = &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(move _5);
14    _6 = Vec::&lt;i32&gt;::len(move _7);
15    _2 = core::slice::&lt;impl [i32]&gt;::rotate_right(move _3, move _6);
16}
17fn foo() -&gt; () {
18    _4 = Vec::&lt;i32&gt;::len(move _5);
19    _2 = Vec::&lt;i32&gt;::resize(move _3, move _4, const 0_i32);
20}
21let dereferenced_vec = &amp;mut *vec;
22let len = vec.len();
23dereferencec_vec.rotate_right(len);
24

Which is obviously a violation of the borrow rules.

On the other hand, vec.resize(vec.len()) has no work to do on the callee (vec), and so we first evaluate vec.len(), and then the call itself.

Solving this is as easy as extracting the vec.len() to a new line (new statement, to be precise), and the compiler also suggests that.

Source https://stackoverflow.com/questions/71823410

Community Discussions contain sources that include Stack Exchange Network

    Why is Rust NLL not working for multiple borrows in the same statement?
    Docker push to AWS ECR hangs immediately and times out
    How does Java know which overloaded method to call with lambda expressions? (Supplier, Consumer, Callable, ...)
    pip-compile raising AssertionError on its logging handler
    Is if(A | B) always faster than if(A || B)?
    What is the proper evaluation order when assigning a value in a map?
    Unable to specify `edition2021` in order to use unstable packages in Rust
    Android Studio strange code sub-windows after upgrade to Arctic Fox (2020.3.1)
    ellipsis ... as function in substitute?
    Python 3.10 pattern matching (PEP 634) - wildcard in string

QUESTION

Why is Rust NLL not working for multiple borrows in the same statement?

Asked 2022-Apr-12 at 00:43

First, I tried something like this:

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3

It can't be compiled because:

error[E0502]: cannot borrow `vec` as immutable because it is also borrowed as mutable

I thought that the Rust borrow checker could be smarter than this, so I found something called NLL, and it should solve this problem.

I tried the sample:

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5

It could work, but why is it not working with rotate_right? Both of them take a &mut self. What's going on?

ANSWER

Answered 2022-Apr-12 at 00:43

It is definitely an interesting one.

They are similar - but not quite the same. resize() is a member of Vec. rotate_right(), on the other hand, is a method of slices.

Vec<T> derefs to [T], so most of the time this does not matter. But actually, while this call:

copy icondownload icon

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6

Desugars to something like:

copy icondownload icon

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7

This call:

copy icondownload icon

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7vec.rotate_right(vec.len());
8

Is more like:

copy icondownload icon

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7vec.rotate_right(vec.len());
8&lt;[i32]&gt;::rotate_right(
9    &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(&amp;mut vec),
10    &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec),
11);
12

But in what order?

This is the MIR for rotate_right() (simplified a lot):

copy icondownload icon

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7vec.rotate_right(vec.len());
8&lt;[i32]&gt;::rotate_right(
9    &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(&amp;mut vec),
10    &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec),
11);
12fn foo() -&gt; () {
13    _4 = &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(move _5);
14    _6 = Vec::&lt;i32&gt;::len(move _7);
15    _2 = core::slice::&lt;impl [i32]&gt;::rotate_right(move _3, move _6);
16}
17

And this is the MIR for resize() (again, simplified a lot):

copy icondownload icon

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7vec.rotate_right(vec.len());
8&lt;[i32]&gt;::rotate_right(
9    &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(&amp;mut vec),
10    &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec),
11);
12fn foo() -&gt; () {
13    _4 = &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(move _5);
14    _6 = Vec::&lt;i32&gt;::len(move _7);
15    _2 = core::slice::&lt;impl [i32]&gt;::rotate_right(move _3, move _6);
16}
17fn foo() -&gt; () {
18    _4 = Vec::&lt;i32&gt;::len(move _5);
19    _2 = Vec::&lt;i32&gt;::resize(move _3, move _4, const 0_i32);
20}
21

In the resize() example, we first call Vec::len() with a reference to vec. This returns usize. Then we call Vec::resize(), when we have no outstanding references to vec, so mutably borrowing it is fine!

However, with rotate_right(), first we call <Vec<i32> as DerefMut>::deref_mut(&mut vec). This returns &mut [i32], with its lifetime tied to vec. That is, as long as this reference (mutable reference!) is alive, we are not allowed to use have any other reference to vec. But then we try to borrow vec in order to pass the (shared, but it doesn't matter) reference to Vec::len(), while we still need to use the mutable reference from deref_mut() later, in the call to <[i32]>::rotate_right()! This is an error.

This is because Rust defines an evaluation order for operands:

Expressions taking multiple operands are evaluated left to right as written in the source code.

Because vec.resize() is actually (&mut *vec).rotate_right(), we first evaluate the dereference+reference, then the arguments:

copy icondownload icon

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7vec.rotate_right(vec.len());
8&lt;[i32]&gt;::rotate_right(
9    &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(&amp;mut vec),
10    &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec),
11);
12fn foo() -&gt; () {
13    _4 = &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(move _5);
14    _6 = Vec::&lt;i32&gt;::len(move _7);
15    _2 = core::slice::&lt;impl [i32]&gt;::rotate_right(move _3, move _6);
16}
17fn foo() -&gt; () {
18    _4 = Vec::&lt;i32&gt;::len(move _5);
19    _2 = Vec::&lt;i32&gt;::resize(move _3, move _4, const 0_i32);
20}
21let dereferenced_vec = &amp;mut *vec;
22let len = vec.len();
23dereferencec_vec.rotate_right(len);
24

Which is obviously a violation of the borrow rules.

On the other hand, vec.resize(vec.len()) has no work to do on the callee (vec), and so we first evaluate vec.len(), and then the call itself.

Solving this is as easy as extracting the vec.len() to a new line (new statement, to be precise), and the compiler also suggests that.

Source https://stackoverflow.com/questions/71823410