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

Modify MIR building to drop repeat expressions with length zero #95953

Merged
merged 1 commit into from
May 25, 2022

Conversation

JakobDegen
Copy link
Contributor

@JakobDegen JakobDegen commented Apr 11, 2022

Closes #74836 .

Previously, when a user wrote [foo; 0] we used to simply leak foo. The goal is to fix that. This PR changes MIR building to make [foo; 0] equivalent to { drop(foo); [] } in all cases. Of course, this is a breaking change (see below). A crater run did not indicate any regressions though, and given that the previous behavior was almost definitely not what any user wanted, it seems unlikely that anyone was relying on this.

Note that const generics are in general unaffected by this. Inserting the extra drop is only meaningful/necessary when foo is of a non-Copy type, and array repeat expressions with const generic repetition count must always be Copy.

Besides the obvious change to behavior associated with the additional drop, there are three categories of examples where this also changes observable behavior. In all of these cases, the new behavior is consistent with what you would get by replacing [foo; 0] with { drop(foo); [] }. As such, none of these give the user new powers to express more things.

No longer allowed in const (breaking):

const _: [String; 0] = [String::new(); 0];

This compiles on stable today. Because we now introduce the drop of String, this no longer compiles as String may not be dropped in a const context.

Reduced dataflow (non-breaking):

let mut x: i32 = 0;
let r = &x;
let a = [r; 0];
x = 5;
let _b = a;

Borrowck rejects this code on stable because it believes there is dataflow between a and r, and so the lifetime of r has to extend to the last statement. This change removes the dataflow and the above code is allowed to compile.

More const promotion (non-breaking):

let _v: &'static [String; 0] = &[String::new(); 0];

This does not compile today because String having drop glue keeps it from being const promoted (despite that drop glue never being executed). After this change, this is allowed to compile.

Alternatives

A previous attempt at this tried to reduce breakage by various tricks. This is still a possibility, but given that crater showed no regressions it seems unclear why we would want to introduce this complexity.

Disallowing [foo; 0] completely is also an option, but obviously this is more of a breaking change. I do not know how often this is actually used though.

r? @oli-obk

@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Apr 11, 2022
@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 11, 2022
@oli-obk
Copy link
Contributor

oli-obk commented Apr 12, 2022

cc @RalfJung we're preventing to promote [String::new(); 0] while fixing it that the element is actually dropped instead of leaked. We avoid this by not changing the mir (in a meaningful way) until after promotion and before borrowck.

@oli-obk
Copy link
Contributor

oli-obk commented Apr 12, 2022

Please reference the bug in the main post and re-explain what the problem is and what code is now changed, as we'll want to nominate this for the lang team. Technically this is a breaking change after all.

Running it through crater, too

@bors try

@bors
Copy link
Contributor

bors commented Apr 12, 2022

⌛ Trying commit 91095c988f099cb0b7d2d7a793e91c1593e9d789 with merge cd1dad2c64d4db00cf381bc072bc07c5230963ce...

@bors
Copy link
Contributor

bors commented Apr 12, 2022

☀️ Try build successful - checks-actions
Build commit: cd1dad2c64d4db00cf381bc072bc07c5230963ce (cd1dad2c64d4db00cf381bc072bc07c5230963ce)

@oli-obk
Copy link
Contributor

oli-obk commented Apr 12, 2022

@craterbot check

@craterbot
Copy link
Collaborator

👌 Experiment pr-95953 created and queued.
🤖 Automatically detected try build cd1dad2c64d4db00cf381bc072bc07c5230963ce
🔍 You can check out the queue and this experiment's details.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 12, 2022
@JakobDegen
Copy link
Contributor Author

I was very tired by the time I put up this PR yesterday, so I got a little bit lazy 😅 . I've updated the PR description with a summary of the situation, which should hopefully be enough information for T-Lang to be able to make an informed decision (if this is discussed at triage today I can also be there)

@oli-obk oli-obk added the I-lang-nominated The issue / PR has been nominated for discussion during a lang team meeting. label Apr 12, 2022
@RalfJung
Copy link
Member

RalfJung commented Apr 12, 2022

cc @RalfJung we're preventing to promote [String::new(); 0] while fixing it that the element is actually dropped instead of leaked. We avoid this by not changing the mir (in a meaningful way) until after promotion and before borrowck.

I think we should break code like in "snippet A". It should never have worked to begin with.

What is the problem with allowing code like "snippet B"?

and then immediately after borrowck changing it to this if we are in a non-const context:

Honestly, this sounds like a terrible hack that will come to bite us later.

@JakobDegen
Copy link
Contributor Author

JakobDegen commented Apr 12, 2022

I don't have strong opinions on breaking snippet A, mostly because I don't have enough experience with how these decisions are made.

What is the problem with allowing code like "snippet B"?

Quoting the reference:

Promotion of a value expression to a 'static slot occurs when the expression could be written in a constant and borrowed, and that borrow could be dereferenced where the expression was originally written, without changing the runtime behavior.

I'm interpreting this to mean that &expr should const promote if &*const { &expr } would work. In the case of &[String::new(); 0], const { &[String::new(); 0] } would not be allowed, and so it should not const promote.

Half related sidenote about implementation

I actually find it somewhat surprising that we chose to implement this in terms of a dataflow analysis. As written, the definition seems to be a mostly syntactic one, and so dataflow would not be my first choice. Is there some complexity here that I'm missing, or some historical details that make this necessary?

Honestly, this sounds like a terrible hack that will come to bite us later.

Agreed. That being said, I'm going to claim that given how horrible the requirements that have emerged are, our options are either to change the requirements or have a terribly hacky implementation. I'm honestly somewhat surprised that the requirements under which I was operating could be implemented with this little code

@RalfJung
Copy link
Member

I don't have strong opinions on breaking snippet A, mostly because I don't have enough experience with how these decisions are made.

If crater doesn't find a case of this happening in the wild, the teams are usually on-board with doing the breaking change. We had a bunch of those around promotion last year.

I'm interpreting this to mean that &expr should const promote if &*const { &expr } would work. In the case of &[String::new(); 0], const { &[String::new(); 0] } would not be allowed, and so it should not const promote.

I'd be shocked if that was the only such example.

Promotion is a lot more subtle than that, e.g. when you write &(A+B), the addition gets promoted but the assertion in case of overflow remains unpromoted. With &something[idx] we sometimes promote the &something but leave the indexing to runtime (because the index is dynamic). This list probably goes on.

Also see this document, but I don't think it is complete either, unfortunately.

At this point, as far as I am concerned, promotion is mostly something we keep around to keep old code working. Anything more complicated than &42 works "by accident". My biggest concern is keeping the promotion implementation as simple as possible, since it has been a huge source of pain (and bugs, even some soundness bugs) in the past.

If there is a nice way to prevent &[String::new(); 0] from being promoted, sure. But first constructing "wrong" MIR and then ad-hoc patching it later?!? That's not worth it.

Agreed. That being said, I'm going to claim that given how horrible the requirements that have emerged are, our options are either to change the requirements or have a terribly hacky implementation. I'm honestly somewhat surprised that the requirements under which I was operating could be implemented with this little code

So let's change those requirements then. :)

@RalfJung
Copy link
Member

RalfJung commented Apr 12, 2022

Maybe promotion analysis should have remained on HIR or THIR, it seems easier to specify and contain that way...

I actually find it somewhat surprising that we chose to implement this in terms of a dataflow analysis. As written, the definition seems to be a mostly syntactic one, and so dataflow would not be my first choice. Is there some complexity here that I'm missing, or some historical details that make this necessary?

It's just how things developed historically. Promotion analysis used to be in the same pass as "check if this is const-compatible", and it used to work on HIR. Basically nothing around promotion was ever "designed" -- it all just "happened" over time. In 2020 I managed to cut away most of that cruft without breaking a lot of code. I then ran out of energy and ideas on how to further improve the situation.

Also see

@JakobDegen
Copy link
Contributor Author

Yeah, this makes sense to me. Possibly we should cancel the crater run, pending a T-Lang response?

@oli-obk

This comment was marked as resolved.

@craterbot

This comment was marked as resolved.

@oli-obk
Copy link
Contributor

oli-obk commented Apr 12, 2022

@craterbot abort

@craterbot
Copy link
Collaborator

🗑️ Experiment pr-95953 deleted!

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-crater Status: Waiting on a crater run to be completed. labels Apr 12, 2022
@oli-obk
Copy link
Contributor

oli-obk commented Apr 12, 2022

We can just crater the version that breaks A and allows B (so basically your original one 😆 ) and then present the result to the lang team. It's easier to talk about if we have data

@oli-obk oli-obk removed the I-lang-nominated The issue / PR has been nominated for discussion during a lang team meeting. label Apr 12, 2022
@JakobDegen
Copy link
Contributor Author

The new version breaks A and allows B. I took some extra time to learn about how drops work in MIR building, and I believe this should do the right thing. The diagnostic on snippet A leaves a little to be desired, but that probably shouldn't block the crater run.

One interesting thing to note is that this change teaches MIR that there is no dataflow dependency between foo and bar in let foo = [bar; 0]; That seems like what we want, since it is after all true, but this is at least a little orthogonal to the drop stuff

@RalfJung
Copy link
Member

RalfJung commented Apr 13, 2022

One interesting thing to note is that this change teaches MIR that there is no dataflow dependency between foo and bar in let foo = [bar; 0]; That seems like what we want, since it is after all true, but this is at least a little orthogonal to the drop stuff

FWIW, if there is a nice way to pretend to dataflow that such a dependency exists, I wouldn't be opposed to that -- as long as it can be added during MIR building, not as a post-doc semantics-changing MIR-patching transformation.

@bors
Copy link
Contributor

bors commented May 24, 2022

📌 Commit 44410ef has been approved by oli-obk

@bors bors added the S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. label May 24, 2022
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request May 24, 2022
Modify MIR building to drop repeat expressions with length zero

Closes rust-lang#74836 .

Previously, when a user wrote `[foo; 0]` we used to simply leak `foo`. The goal is to fix that. This PR changes MIR building to make `[foo; 0]` equivalent to `{ drop(foo); [] }` in all cases. Of course, this is a breaking change (see below). A crater run did not indicate any regressions though, and given that the previous behavior was almost definitely not what any user wanted, it seems unlikely that anyone was relying on this.

Note that const generics are in general unaffected by this. Inserting the extra `drop` is only meaningful/necessary when `foo` is of a non-`Copy` type, and array repeat expressions with const generic repetition count must always be `Copy`.

Besides the obvious change to behavior associated with the additional drop, there are three categories of examples where this also changes observable behavior. In all of these cases, the new behavior is consistent with what you would get by replacing `[foo; 0]` with `{ drop(foo); [] }`. As such, none of these give the user new powers to express more things.

**No longer allowed in const (breaking)**:

```rust
const _: [String; 0] = [String::new(); 0];
```

This compiles on stable today. Because we now introduce the drop of `String`, this no longer compiles as `String` may not be dropped in a const context.

**Reduced dataflow (non-breaking)**:

```rust
let mut x: i32 = 0;
let r = &x;
let a = [r; 0];
x = 5;
let _b = a;
```

Borrowck rejects this code on stable because it believes there is dataflow between `a` and `r`, and so the lifetime of `r` has to extend to the last statement. This change removes the dataflow and the above code is allowed to compile.

**More const promotion (non-breaking)**:

```rust
let _v: &'static [String; 0] = &[String::new(); 0];
```

This does not compile today because `String` having drop glue keeps it from being const promoted (despite that drop glue never being executed). After this change, this is allowed to compile.

### Alternatives

A previous attempt at this tried to reduce breakage by various tricks. This is still a possibility, but given that crater showed no regressions it seems unclear why we would want to introduce this complexity.

Disallowing `[foo; 0]` completely is also an option, but obviously this is more of a breaking change. I do not know how often this is actually used though.

r? `@oli-obk`
@bors
Copy link
Contributor

bors commented May 24, 2022

⌛ Testing commit 44410ef with merge 1577bcc8461b0acd25cc943a075be2207283baa1...

@JohnTitor
Copy link
Member

Failed in rollup: #97347 (comment)
Needs to ignore some targets on the tests

@bors retry r-

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels May 24, 2022
@RalfJung
Copy link
Member

@bors rollup=iffy

@rust-log-analyzer

This comment has been minimized.

@JakobDegen
Copy link
Contributor Author

Added a bunch of ignore directives, stolen from src/test/ui/runtime/rt-explody-panic-payloads.rs

@oli-obk
Copy link
Contributor

oli-obk commented May 25, 2022

@bors r+

@bors
Copy link
Contributor

bors commented May 25, 2022

📌 Commit 0f65bcd has been approved by oli-obk

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 25, 2022
bors added a commit to rust-lang-ci/rust that referenced this pull request May 25, 2022
Rollup of 5 pull requests

Successful merges:

 - rust-lang#95953 (Modify MIR building to drop repeat expressions with length zero)
 - rust-lang#96913 (RFC3239: Implement `cfg(target)` - Part 2)
 - rust-lang#97233 ([RFC 2011] Library code)
 - rust-lang#97370 (Minor improvement on else-no-if diagnostic)
 - rust-lang#97384 (Fix metadata stats.)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors
Copy link
Contributor

bors commented May 25, 2022

⌛ Testing commit 0f65bcd with merge fe9c64d...

@bors bors merged commit 11faf2e into rust-lang:master May 25, 2022
@rustbot rustbot added this to the 1.63.0 milestone May 25, 2022
@rfcbot rfcbot added finished-final-comment-period The final comment period is finished for this PR / Issue. to-announce Announce this issue on triage meeting and removed final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. labels May 27, 2022
@JakobDegen JakobDegen deleted the repeat-leak branch May 28, 2022 01:29
@apiraino apiraino removed the to-announce Announce this issue on triage meeting label Sep 8, 2022
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Oct 10, 2022
Pkgsrc changes:
 * Adjust patches as needed & checksum updates.

Upstream changes:

Version 1.63.0 (2022-08-11)
==========================

Language
--------
- [Remove migrate borrowck mode for pre-NLL errors.][95565]
- [Modify MIR building to drop repeat expressions with length zero.][95953]
- [Remove label/lifetime shadowing warnings.][96296]
- [Allow explicit generic arguments in the presence of `impl Trait` args.]
  [96868]
- [Make `cenum_impl_drop_cast` warnings deny-by-default.][97652]
- [Prevent unwinding when `-C panic=abort` is used regardless of
  declared ABI.][96959]
- [lub: don't bail out due to empty binders.][97867]

Compiler
--------
- [Stabilize the `bundle` native library modifier,][95818] also removing the
  deprecated `static-nobundle` linking kind.
- [Add Apple WatchOS compile targets\*.][95243]
- [Add a Windows application manifest to rustc-main.][96737]

\* Refer to Rust's [platform support page][platform-support-doc] for more
   information on Rust's tiered platform support.

Libraries
---------
- [Implement `Copy`, `Clone`, `PartialEq` and `Eq` for
  `core::fmt::Alignment`.][94530]
- [Extend `ptr::null` and `null_mut` to all thin (including extern)
  types.][94954]
- [`impl Read and Write for VecDeque<u8>`.][95632]
- [STD support for the Nintendo 3DS.][95897]
- [Make write/print macros eagerly drop temporaries.][96455]
- [Implement internal traits that enable `[OsStr]::join`.][96881]
- [Implement `Hash` for `core::alloc::Layout`.][97034]
- [Add capacity documentation for `OsString`.][97202]
- [Put a bound on collection misbehavior.][97316]
- [Make `std::mem::needs_drop` accept `?Sized`.][97675]
- [`impl Termination for Infallible` and then make the `Result` impls
  of `Termination` more generic.][97803]
- [Document Rust's stance on `/proc/self/mem`.][97837]

Stabilized APIs
---------------

- [`array::from_fn`]
- [`Box::into_pin`]
- [`BinaryHeap::try_reserve`]
- [`BinaryHeap::try_reserve_exact`]
- [`OsString::try_reserve`]
- [`OsString::try_reserve_exact`]
- [`PathBuf::try_reserve`]
- [`PathBuf::try_reserve_exact`]
- [`Path::try_exists`]
- [`Ref::filter_map`]
- [`RefMut::filter_map`]
- [`NonNull::<[T]>::len`][`NonNull::<slice>::len`]
- [`ToOwned::clone_into`]
- [`Ipv6Addr::to_ipv4_mapped`]
- [`unix::io::AsFd`]
- [`unix::io::BorrowedFd<'fd>`]
- [`unix::io::OwnedFd`]
- [`windows::io::AsHandle`]
- [`windows::io::BorrowedHandle<'handle>`]
- [`windows::io::OwnedHandle`]
- [`windows::io::HandleOrInvalid`]
- [`windows::io::HandleOrNull`]
- [`windows::io::InvalidHandleError`]
- [`windows::io::NullHandleError`]
- [`windows::io::AsSocket`]
- [`windows::io::BorrowedSocket<'handle>`]
- [`windows::io::OwnedSocket`]
- [`thread::scope`]
- [`thread::Scope`]
- [`thread::ScopedJoinHandle`]

These APIs are now usable in const contexts:

- [`array::from_ref`]
- [`slice::from_ref`]
- [`intrinsics::copy`]
- [`intrinsics::copy_nonoverlapping`]
- [`<*const T>::copy_to`]
- [`<*const T>::copy_to_nonoverlapping`]
- [`<*mut T>::copy_to`]
- [`<*mut T>::copy_to_nonoverlapping`]
- [`<*mut T>::copy_from`]
- [`<*mut T>::copy_from_nonoverlapping`]
- [`str::from_utf8`]
- [`Utf8Error::error_len`]
- [`Utf8Error::valid_up_to`]
- [`Condvar::new`]
- [`Mutex::new`]
- [`RwLock::new`]

Cargo
-----
- [Stabilize the `--config path` command-line argument.][cargo/10755]
- [Expose rust-version in the environment as
  `CARGO_PKG_RUST_VERSION`.][cargo/10713]

Compatibility Notes
-------------------

- [`#[link]` attributes are now checked more strictly,][96885]
  which may introduce errors for invalid attribute arguments that
  were previously ignored.

Internal Changes
----------------

These changes provide no direct user facing benefits, but represent
significant improvements to the internals and overall performance
of rustc and related tools.

- [Prepare Rust for LLVM opaque pointers.][94214]

[94214]: rust-lang/rust#94214
[94530]: rust-lang/rust#94530
[94954]: rust-lang/rust#94954
[95243]: rust-lang/rust#95243
[95565]: rust-lang/rust#95565
[95632]: rust-lang/rust#95632
[95818]: rust-lang/rust#95818
[95897]: rust-lang/rust#95897
[95953]: rust-lang/rust#95953
[96296]: rust-lang/rust#96296
[96455]: rust-lang/rust#96455
[96737]: rust-lang/rust#96737
[96868]: rust-lang/rust#96868
[96881]: rust-lang/rust#96881
[96885]: rust-lang/rust#96885
[96959]: rust-lang/rust#96959
[97034]: rust-lang/rust#97034
[97202]: rust-lang/rust#97202
[97316]: rust-lang/rust#97316
[97652]: rust-lang/rust#97652
[97675]: rust-lang/rust#97675
[97803]: rust-lang/rust#97803
[97837]: rust-lang/rust#97837
[97867]: rust-lang/rust#97867
[cargo/10713]: rust-lang/cargo#10713
[cargo/10755]: rust-lang/cargo#10755

[`array::from_fn`]: https://doc.rust-lang.org/stable/std/array/fn.from_fn.html
[`Box::into_pin`]: https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#method.into_pin
[`BinaryHeap::try_reserve_exact`]: https://doc.rust-lang.org/stable/alloc/collections/binary_heap/struct.BinaryHeap.html#method.try_reserve_exact
[`BinaryHeap::try_reserve`]: https://doc.rust-lang.org/stable/std/collections/struct.BinaryHeap.html#method.try_reserve
[`OsString::try_reserve`]: https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.try_reserve
[`OsString::try_reserve_exact`]: https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.try_reserve_exact
[`PathBuf::try_reserve`]: https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#method.try_reserve
[`PathBuf::try_reserve_exact`]: https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#method.try_reserve_exact
[`Path::try_exists`]: https://doc.rust-lang.org/stable/std/path/struct.Path.html#method.try_exists
[`Ref::filter_map`]: https://doc.rust-lang.org/stable/std/cell/struct.Ref.html#method.filter_map
[`RefMut::filter_map`]: https://doc.rust-lang.org/stable/std/cell/struct.RefMut.html#method.filter_map
[`NonNull::<slice>::len`]: https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.len
[`ToOwned::clone_into`]: https://doc.rust-lang.org/stable/std/borrow/trait.ToOwned.html#method.clone_into
[`Ipv6Addr::to_ipv4_mapped`]: https://doc.rust-lang.org/stable/std/net/struct.Ipv6Addr.html#method.to_ipv4_mapped
[`unix::io::AsFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.AsFd.html
[`unix::io::BorrowedFd<'fd>`]: https://doc.rust-lang.org/stable/std/os/unix/io/struct.BorrowedFd.html
[`unix::io::OwnedFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/struct.OwnedFd.html
[`windows::io::AsHandle`]: https://doc.rust-lang.org/stable/std/os/windows/io/trait.AsHandle.html
[`windows::io::BorrowedHandle<'handle>`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.BorrowedHandle.html
[`windows::io::OwnedHandle`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.OwnedHandle.html
[`windows::io::HandleOrInvalid`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.HandleOrInvalid.html
[`windows::io::HandleOrNull`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.HandleOrNull.html
[`windows::io::InvalidHandleError`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.InvalidHandleError.html
[`windows::io::NullHandleError`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.NullHandleError.html
[`windows::io::AsSocket`]: https://doc.rust-lang.org/stable/std/os/windows/io/trait.AsSocket.html
[`windows::io::BorrowedSocket<'handle>`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.BorrowedSocket.html
[`windows::io::OwnedSocket`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.OwnedSocket.html
[`thread::scope`]: https://doc.rust-lang.org/stable/std/thread/fn.scope.html
[`thread::Scope`]: https://doc.rust-lang.org/stable/std/thread/struct.Scope.html
[`thread::ScopedJoinHandle`]: https://doc.rust-lang.org/stable/std/thread/struct.ScopedJoinHandle.html

[`array::from_ref`]: https://doc.rust-lang.org/stable/std/array/fn.from_ref.html
[`slice::from_ref`]: https://doc.rust-lang.org/stable/std/slice/fn.from_ref.html
[`intrinsics::copy`]: https://doc.rust-lang.org/stable/std/intrinsics/fn.copy.html
[`intrinsics::copy_nonoverlapping`]: https://doc.rust-lang.org/stable/std/intrinsics/fn.copy_nonoverlapping.html
[`<*const T>::copy_to`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_to
[`<*const T>::copy_to_nonoverlapping`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_to_nonoverlapping
[`<*mut T>::copy_to`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_to-1
[`<*mut T>::copy_to_nonoverlapping`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_to_nonoverlapping-1
[`<*mut T>::copy_from`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_from
[`<*mut T>::copy_from_nonoverlapping`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_from_nonoverlapping
[`str::from_utf8`]: https://doc.rust-lang.org/stable/std/str/fn.from_utf8.html
[`Utf8Error::error_len`]: https://doc.rust-lang.org/stable/std/str/struct.Utf8Error.html#method.error_len
[`Utf8Error::valid_up_to`]: https://doc.rust-lang.org/stable/std/str/struct.Utf8Error.html#method.valid_up_to
[`Condvar::new`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.new
[`Mutex::new`]: https://doc.rust-lang.org/stable/std/sync/struct.Mutex.html#method.new
[`RwLock::new`]: https://doc.rust-lang.org/stable/std/sync/struct.RwLock.html#method.new
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. S-waiting-on-fcp Status: PR is in FCP and is awaiting for FCP to complete. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Initializing a zero-length array leaks the initializer