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

Make RwLockReadGuard covariant #96820

Merged
merged 12 commits into from
Jun 25, 2022
Merged

Make RwLockReadGuard covariant #96820

merged 12 commits into from
Jun 25, 2022

Conversation

r-raymond
Copy link
Contributor

@r-raymond r-raymond commented May 7, 2022

Hi, first time contributor here, if anything is not as expected, please let me know.

RwLockReadGoard's type constructor is invariant. Since it behaves like a smart pointer to an immutable reference, there is no reason that it should not be covariant. Take e.g.

fn test_read_guard_covariance() {
    fn do_stuff<'a>(_: RwLockReadGuard<'_, &'a i32>, _: &'a i32) {}
    let j: i32 = 5;
    let lock = RwLock::new(&j);
    {
        let i = 6;
        do_stuff(lock.read().unwrap(), &i);
    }
    drop(lock);
}

where the compiler complains that &i doesn't live long enough. If RwLockReadGuard is covariant, then the above code is accepted because the lifetime can be shorter than 'a.

In order for RwLockReadGuard to be covariant, it can't contain a full reference to the RwLock, which can never be covariant (because it exposes a mutable reference to the underlying data structure). By reducing the data structure to the required pieces of RwLock, the rest falls in place.

If there is a better way to do a test that tests successful compilation, please let me know.

Fixes #80392

@rust-highfive
Copy link
Collaborator

Hey! It looks like you've submitted a new PR for the library teams!

If this PR contains changes to any rust-lang/rust public library APIs then please comment with r? rust-lang/libs-api @rustbot label +T-libs-api -T-libs to request review from a libs-api team reviewer. If you're unsure where your change falls no worries, just leave it as is and the reviewer will take a look and make a decision to forward on if necessary.

Examples of T-libs-api changes:

  • Stabilizing library features
  • Introducing insta-stable changes such as new implementations of existing stable traits on existing stable types
  • Introducing new or changing existing unstable library APIs (excluding permanently unstable features / features without a tracking issue)
  • Changing public documentation in ways that create new stability guarantees
  • Changing observable runtime behavior of library APIs

@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @Mark-Simulacrum (or someone else) soon.

Please see the contribution instructions for more information.

@rustbot rustbot added the T-libs Relevant to the library team, which will review and decide on the PR/issue. label May 7, 2022
@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 7, 2022
@Mark-Simulacrum Mark-Simulacrum added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. and removed T-libs Relevant to the library team, which will review and decide on the PR/issue. labels May 7, 2022
@m-ou-se
Copy link
Member

m-ou-se commented May 9, 2022

@rfcbot merge

@rfcbot
Copy link

rfcbot commented May 9, 2022

Team member @m-ou-se has proposed to merge this. The next step is review by the rest of the tagged team members:

No concerns currently listed.

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@rfcbot rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. and removed proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. labels May 9, 2022
@rfcbot
Copy link

rfcbot commented May 10, 2022

🔔 This is now entering its final comment period, as per the review above. 🔔

@RustyYato
Copy link
Contributor

I don't think this change is sound because of problems like this:

tldr: with this change Ref gets the noalias attribute (from the reference), which is unsound.

In fact, if we check the IR we see a noalias attribute with the new change, but not the existing code.

https://rust.godbolt.org/z/jbe6Yah6j

struct RefCell<T: ?Sized> {
    borrow_flag: core::cell::Cell<usize>,
    cell: core::cell::UnsafeCell<T>,
}

struct RefStd<'a, T> {
    cell: &'a RefCell<T>,
}

struct Ref<'a, T> {
    cell: &'a core::cell::Cell<usize>,
    value: &'a T,
}

// has noalias
#[no_mangle] fn foo(rc: &RefCell<i32>, r: Ref<'_, i32>) {}
// does not have noalias
#[no_mangle] fn bar(rc: &RefCell<i32>, r: RefStd<'_, i32>) {}

generated llvm-ir

; ModuleID = 'example.6cc7c99e-cgu.0'
source_filename = "example.6cc7c99e-cgu.0"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: mustprogress nofree norecurse nosync nounwind nonlazybind readnone willreturn
define void @foo({ i64, i32 }* nocapture noundef align 8 dereferenceable(16) %rc, i64* nocapture noundef align 8 dereferenceable(8) %r.0, i32* noalias nocapture noundef readonly align 4 dereferenceable(4) %r.1) unnamed_addr #0 {
start:
  ret void
}

; Function Attrs: mustprogress nofree norecurse nosync nounwind nonlazybind readnone willreturn
define void @bar({ i64, i32 }* nocapture noundef align 8 dereferenceable(16) %rc, i64* nocapture noundef align 8 dereferenceable(16) %r) unnamed_addr #0 {
start:
  ret void
}

attributes #0 = { mustprogress nofree norecurse nosync nounwind nonlazybind readnone willreturn "probe-stack"="__rust_probestack" "target-cpu"="x86-64" }

!llvm.module.flags = !{!0, !1}

!0 = !{i32 7, !"PIC Level", i32 2}
!1 = !{i32 2, !"RtLibUseGOT", i32 1}

@coolreader18
Copy link
Contributor

Separately from the soundness concern; should the data: &T field be first? It's a lot more common to access the data than the mutex, and so then it could compile to the same as a pointer access without having to add an offset. (Maybe?)

@r-raymond
Copy link
Contributor Author

r-raymond commented May 13, 2022

Hi @RustyYato, thanks for speaking up, I was not aware of the noalias problem. Seems like the designated "fix" (replacing by * const) also works in this case.

struct RefCell<T: ?Sized> {
    borrow_flag: core::cell::Cell<usize>,
    cell: core::cell::UnsafeCell<T>,
}

struct RefStd<'a, T> {
    cell: &'a RefCell<T>,
}

struct Ref<'a, T> {
    cell: &'a core::cell::Cell<usize>,
    value: &'a T,
}

struct RefNew<'a, T> {
    value: *const T,
    cell: &'a core::cell::Cell<usize>,
}

// has noalias
#[no_mangle] fn foo(rc: &RefCell<i32>, r: Ref<'_, i32>) {}
// does not have noalias
#[no_mangle] fn bar(rc: &RefCell<i32>, r: RefStd<'_, i32>) {}
// does not have noalias
#[no_mangle] fn baz(rc: &RefCell<i32>, r: RefNew<'_, i32>) {}
; Function Attrs: mustprogress nofree norecurse nosync nounwind nonlazybind readnone willreturn
define void @foo({ i64, i32 }* nocapture noundef align 8 dereferenceable(16) %rc, i64* nocapture noundef align 8 dereferenceable(8) %r.0, i32* noalias nocapture noundef readonly align 4 dereferenceable(4) %r.1) unnamed_addr #0 {
start:
  ret void
}

; Function Attrs: mustprogress nofree norecurse nosync nounwind nonlazybind readnone willreturn
define void @bar({ i64, i32 }* nocapture noundef align 8 dereferenceable(16) %rc, i64* nocapture noundef align 8 dereferenceable(16) %r) unnamed_addr #0 {
start:
  ret void
}

; Function Attrs: mustprogress nofree norecurse nosync nounwind nonlazybind readnone willreturn
define void @baz({ i64, i32 }* nocapture noundef align 8 dereferenceable(16) %rc, i32* nocapture %r.0, i64* nocapture noundef align 8 dereferenceable(8) %r.1) unnamed_addr #0 {
start:
  ret void
}

(see https://rust.godbolt.org/z/GrKP9oT99).

Luckily * const preserves our covariancy, so this still solved the initial problem. Any objections to making this modification by the existing reviewers?

@r-raymond
Copy link
Contributor Author

r-raymond commented May 13, 2022

Thanks for the suggestion @coolreader18. Seems like there shouldn't be a difference for most architectures:

use std::ops::Deref;

struct Test1<'a, T: ?Sized> {
    cell: &'a core::cell::Cell<usize>,
    data: *const T,
}
struct Test2<'a, T: ?Sized> {
    data: *const T,
    cell: &'a core::cell::Cell<usize>,
}


impl<T: ?Sized> Deref for Test1<'_, T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.data }
    }
}

impl<T: ?Sized> Deref for Test2<'_, T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.data }
    }
}

#[no_mangle] fn t1(t: &Test1<i32>) -> i32 {
    **t
}

#[no_mangle] fn t2(t: &Test2<i32>) -> i32 {
    **t
}

gives

        .text
        .intel_syntax noprefix
        .file   "example.6cc7c99e-cgu.0"
        .section        .text.t1,"ax",@progbits
        .globl  t1
        .p2align        4, 0x90
        .type   t1,@function
t1:
        mov     rax, qword ptr [rdi + 8]
        mov     eax, dword ptr [rax]
        ret
.Lfunc_end0:
        .size   t1, .Lfunc_end0-t1

        .section        .text.t2,"ax",@progbits
        .globl  t2
        .p2align        4, 0x90
        .type   t2,@function
t2:
        mov     rax, qword ptr [rdi]
        mov     eax, dword ptr [rax]
        ret
.Lfunc_end1:
        .size   t2, .Lfunc_end1-t2

        .section        ".note.GNU-stack","",@progbits

(see https://rust.godbolt.org/z/neh1KW6eY)
AFAICT the mov with offset is not more expensive than the mov without offset. However since there is no drawback to your suggestion, I'll go ahead and make the change.

@BurntSushi
Copy link
Member

BurntSushi commented May 13, 2022

I would feel a lot better if the unsafe usages in this PR had safety justifications. And also that the unsafe fn new routine documents what conditions the caller is required to uphold for safety.

@RalfJung
Copy link
Member

Luckily * const preserves our covariancy, so this still solved the initial problem. Any objections to making this modification by the existing reviewers?

You probably want to use NonNull to preserve the niche. But other than that, seems fine to me.

@r-raymond
Copy link
Contributor Author

@RalfJung thanks for the pointer. Seems like NonNull is potentially a bigger footgun, but it makes sense to keep the niche for optimizations. Modified in 1ab5f09

@BurntSushi thanks for the concerns. I have added some documentation to the unsafe fn new's of ReadGuard and WriteGuard. Let me know if you consider this sufficient. I kept it brief considering that there should really be no reason to instantiate these Guards manually, so it is more of an internal documentation.

Wrt the arguments for safety, here is why they are safe.

@@ -536,7 +549,7 @@ fn deref_mut(&mut self) -> &mut T {
 impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
     fn drop(&mut self) {
         unsafe {
-            self.lock.inner.read_unlock();
+            self.inner_lock.read_unlock();
         }
     }
 }

This really doesn't change the behavior from before. However, if the precondition documented on the new function holds, then the current thread has read access, in which case it is safe to call read_unlock according to the documentation of MoveableRwLock.

@@ -512,7 +525,7 @@ impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> {
    type Target = T;

    fn deref(&self) -> &T {
-        unsafe { &*self.lock.data.get() }
+        unsafe { self.data.as_ref() }
    }
}

According to the documentation of NonNull https://doc.rust-lang.org/std/ptr/struct.NonNull.html this is safe if

  • the pointer is properly aligned
  • the pointer is dereferenceable
  • the pointer points to an initialized instance of T
  • Rust's aliasing rules are respected (wrt the lifetime returned)

Making arguments for these points basically takes us through the entire construction of the RwLock. If we accept that &*self.lock.data.get() is safe, then we know than the first 3 points are given. The last point is given since the lifetime is restricted by the lifetime of the RwLockReadGuard. As long as the instance of the latter is alive, we have (shared) read access to the underlying data structure.

Finally

@@ -468,12 +470,23 @@ fn from(t: T) -> Self {
 }

 impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
+    /// Create a new instance of `RwLockReadGuard<T>` from a `RwLock<T>`.
+    ///
+    /// It is safe to call this function if and only if `lock.inner.read()` (or
+    /// `lock.inner.try_read()`) has been successfully called before instantiating this object.
     unsafe fn new(lock: &'rwlock RwLock<T>) -> LockResult<RwLockReadGuard<'rwlock, T>> {
-        poison::map_result(lock.poison.borrow(), |_| RwLockReadGuard { lock })
+        poison::map_result(lock.poison.borrow(), |_| RwLockReadGuard {
+            data: NonNull::new_unchecked(lock.data.get()),
+            inner_lock: &lock.inner,
+        })
     }
 }

The concerning point is NonNull::new_unchecked. Since an initialized RwLock will always hold a valid instance of the underlying object, lock.data.get() can't be null.

Let me know if these arguments are sufficient for you. Happy to dive deeper into anything mentioned here. If anyone else has comments on the above, please share.

@BurntSushi
Copy link
Member

BurntSushi commented May 16, 2022

@r-raymond Thanks! I generally prefer to see SAFETY: comments on all uses of unsafe, but I'll leave that up to @rust-lang/libs, as I'm not terribly familiar with the convention here in std. But your reasoning in the comment makes sense to me. :)

@rfcbot rfcbot added finished-final-comment-period The final comment period is finished for this PR / Issue. and removed final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. labels May 20, 2022
@rfcbot
Copy link

rfcbot commented May 20, 2022

The final comment period, with a disposition to merge, as per the review above, is now complete.

As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.

This will be merged soon.

@rfcbot rfcbot added the to-announce Announce this issue on triage meeting label May 20, 2022
@r-raymond
Copy link
Contributor Author

@BurntSushi: Thanks for the response. I was not aware of the norm around SAFETY comments. Can you share an example (rust and safety is a bit hard to search)? Should we abort the merge and address the issue?

@RalfJung
Copy link
Member

If you grep for 'SAFETY:' in the library folder of this repo, you will find hundreds of examples. :)

@rust-log-analyzer

This comment has been minimized.

@cuviper
Copy link
Member

cuviper commented Jun 21, 2022

@bors r+

@bors
Copy link
Contributor

bors commented Jun 21, 2022

📌 Commit 048a801 has been approved by cuviper

@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-review Status: Awaiting review from the assignee but also interested parties. labels Jun 21, 2022
JohnTitor added a commit to JohnTitor/rust that referenced this pull request Jun 22, 2022
Make RwLockReadGuard covariant

Hi, first time contributor here, if anything is not as expected, please let me know.

`RwLockReadGoard`'s type constructor is invariant. Since it behaves like a smart pointer to an immutable reference, there is no reason that it should not be covariant. Take e.g.

```
fn test_read_guard_covariance() {
    fn do_stuff<'a>(_: RwLockReadGuard<'_, &'a i32>, _: &'a i32) {}
    let j: i32 = 5;
    let lock = RwLock::new(&j);
    {
        let i = 6;
        do_stuff(lock.read().unwrap(), &i);
    }
    drop(lock);
}
```
where the compiler complains that &i doesn't live long enough. If `RwLockReadGuard` is covariant, then the above code is accepted because the lifetime can be shorter than `'a`.

In order for `RwLockReadGuard` to be covariant, it can't contain a full reference to the `RwLock`, which can never be covariant (because it exposes a mutable reference to the underlying data structure). By reducing the data structure to the required pieces of `RwLock`, the rest falls in place.

If there is a better way to do a test that tests successful compilation, please let me know.

Fixes rust-lang#80392
@JohnTitor
Copy link
Member

Seems failed in rollup: #98367 (comment)
@bors 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 Jun 22, 2022
@r-raymond
Copy link
Contributor Author

Seems failed in rollup: #98367 (comment) @bors r-

I have taken a stab at fixing this in 5656de7. However, I don't have access to a windows box. Is there any way I can verify this without one?

@cuviper
Copy link
Member

cuviper commented Jun 22, 2022

I don't know how to test it without Windows, but let's just try it without a rollup, so we don't break others' CI.

@bors r+ rollup=never

@bors
Copy link
Contributor

bors commented Jun 22, 2022

📌 Commit 5656de7 has been approved by cuviper

@bors
Copy link
Contributor

bors commented Jun 22, 2022

🌲 The tree is currently closed for pull requests below priority 1000. This pull request will be tested once the tree is reopened.

@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 Jun 22, 2022
@bors
Copy link
Contributor

bors commented Jun 25, 2022

⌛ Testing commit 5656de7 with merge 00ce472...

@bors
Copy link
Contributor

bors commented Jun 25, 2022

☀️ Test successful - checks-actions
Approved by: cuviper
Pushing 00ce472 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Jun 25, 2022
@bors bors merged commit 00ce472 into rust-lang:master Jun 25, 2022
@rustbot rustbot added this to the 1.64.0 milestone Jun 25, 2022
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (00ce472): comparison url.

Instruction count

  • Primary benchmarks: no relevant changes found
  • Secondary benchmarks: 🎉 relevant improvement found
mean1 max count2
Regressions 😿
(primary)
N/A N/A 0
Regressions 😿
(secondary)
N/A N/A 0
Improvements 🎉
(primary)
N/A N/A 0
Improvements 🎉
(secondary)
-0.7% -0.7% 1
All 😿🎉 (primary) N/A N/A 0

Max RSS (memory usage)

Results
  • Primary benchmarks: 😿 relevant regressions found
  • Secondary benchmarks: 😿 relevant regressions found
mean1 max count2
Regressions 😿
(primary)
2.6% 3.0% 2
Regressions 😿
(secondary)
6.4% 9.1% 2
Improvements 🎉
(primary)
N/A N/A 0
Improvements 🎉
(secondary)
N/A N/A 0
All 😿🎉 (primary) 2.6% 3.0% 2

Cycles

Results
  • Primary benchmarks: 🎉 relevant improvement found
  • Secondary benchmarks: 😿 relevant regression found
mean1 max count2
Regressions 😿
(primary)
N/A N/A 0
Regressions 😿
(secondary)
4.2% 4.2% 1
Improvements 🎉
(primary)
-2.9% -2.9% 1
Improvements 🎉
(secondary)
N/A N/A 0
All 😿🎉 (primary) -2.9% -2.9% 1

If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf.

@rustbot label: -perf-regression

Footnotes

  1. the arithmetic mean of the percent change 2 3

  2. number of relevant changes 2 3

wip-sync pushed a commit to NetBSD/pkgsrc-wip that referenced this pull request Oct 11, 2022
Pkgsrc changes:
 * Add patch to fix vendor/kqueue issue (on 32-bit hosts)
 * Adjust other patches & line numbers
 * Version bumps & checksum changes.

Upstream changes:

Version 1.64.0 (2022-09-22)
===========================

Language
--------
- [Unions with mutable references or tuples of allowed types are
  now allowed](rust-lang/rust#97995)

- It is now considered valid to deallocate memory pointed to by a
  shared reference `&T` [if every byte in `T` is inside an
  `UnsafeCell`](rust-lang/rust#98017)

- Unused tuple struct fields are now warned against in an
  allow-by-default lint, [`unused_tuple_struct_fields`]
  (rust-lang/rust#95977), similar to the
  existing warning for unused struct fields. This lint will become
  warn-by-default in the future.

Compiler
--------
- [Add Nintendo Switch as tier 3 target]
  (rust-lang/rust#88991)
  - Refer to Rust's [platform support page][platform-support-doc] for more
    information on Rust's tiered platform support.
- [Only compile `#[used]` as llvm.compiler.used for ELF targets]
  (rust-lang/rust#93718)
- [Add the `--diagnostic-width` compiler flag to define the terminal width.]
  (rust-lang/rust#95635)
- [Add support for link-flavor `rust-lld` for iOS, tvOS and watchOS]
  (rust-lang/rust#98771)

Libraries
---------
- [Remove restrictions on compare-exchange memory ordering.]
  (rust-lang/rust#98383)
- You can now `write!` or `writeln!` into an `OsString`: [Implement
  `fmt::Write` for `OsString`](rust-lang/rust#97915)
- [Make RwLockReadGuard covariant]
  (rust-lang/rust#96820)
- [Implement `FusedIterator` for `std::net::[Into]Incoming`]
  (rust-lang/rust#97300)
- [`impl<T: AsRawFd> AsRawFd for {Arc,Box}<T>`]
  (rust-lang/rust#97437)
- [`ptr::copy` and `ptr::swap` are doing untyped copies]
  (rust-lang/rust#97712)
- [Add cgroupv1 support to `available_parallelism`]
  (rust-lang/rust#97925)
- [Mitigate many incorrect uses of `mem::uninitialized`]
  (rust-lang/rust#99182)

Stabilized APIs
---------------
- [`future::IntoFuture`]
  (https://doc.rust-lang.org/stable/std/future/trait.IntoFuture.html)
- [`future::poll_fn`]
  (https://doc.rust-lang.org/stable/std/future/fn.poll_fn.html)
- [`task::ready!`]
  (https://doc.rust-lang.org/stable/std/task/macro.ready.html)
- [`num::NonZero*::checked_mul`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.checked_mul)
- [`num::NonZero*::checked_pow`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.checked_pow)
- [`num::NonZero*::saturating_mul`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.saturating_mul)
- [`num::NonZero*::saturating_pow`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.saturating_pow)
- [`num::NonZeroI*::abs`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.abs)
- [`num::NonZeroI*::checked_abs`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.checked_abs)
- [`num::NonZeroI*::overflowing_abs`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.overflowing_abs)
- [`num::NonZeroI*::saturating_abs`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.saturating_abs)
- [`num::NonZeroI*::unsigned_abs`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.unsigned_abs)
- [`num::NonZeroI*::wrapping_abs`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.wrapping_abs)
- [`num::NonZeroU*::checked_add`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.checked_add)
- [`num::NonZeroU*::checked_next_power_of_two`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.checked_next_power_of_two)
- [`num::NonZeroU*::saturating_add`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.saturating_add)
- [`os::unix::process::CommandExt::process_group`]
  (https://doc.rust-lang.org/stable/std/os/unix/process/trait.CommandExt.html#tymethod.process_group)
- [`os::windows::fs::FileTypeExt::is_symlink_dir`]
  (https://doc.rust-lang.org/stable/std/os/windows/fs/trait.FileTypeExt.html#tymethod.is_symlink_dir)
- [`os::windows::fs::FileTypeExt::is_symlink_file`]
  (https://doc.rust-lang.org/stable/std/os/windows/fs/trait.FileTypeExt.html#tymethod.is_symlink_file)

These types were previously stable in `std::ffi`, but are now also
available in `core` and `alloc`:

- [`core::ffi::CStr`]
  (https://doc.rust-lang.org/stable/core/ffi/struct.CStr.html)
- [`core::ffi::FromBytesWithNulError`]
  (https://doc.rust-lang.org/stable/core/ffi/struct.FromBytesWithNulError.html)
- [`alloc::ffi::CString`]
  (https://doc.rust-lang.org/stable/alloc/ffi/struct.CString.html)
- [`alloc::ffi::FromVecWithNulError`]
  (https://doc.rust-lang.org/stable/alloc/ffi/struct.FromVecWithNulError.html)
- [`alloc::ffi::IntoStringError`]
  (https://doc.rust-lang.org/stable/alloc/ffi/struct.IntoStringError.html)
- [`alloc::ffi::NulError`]
  (https://doc.rust-lang.org/stable/alloc/ffi/struct.NulError.html)

These types were previously stable in `std::os::raw`, but are now also available in `core::ffi` and `std::ffi`:

- [`ffi::c_char`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_char.html)
- [`ffi::c_double`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_double.html)
- [`ffi::c_float`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_float.html)
- [`ffi::c_int`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_int.html)
- [`ffi::c_long`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_long.html)
- [`ffi::c_longlong`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_longlong.html)
- [`ffi::c_schar`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_schar.html)
- [`ffi::c_short`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_short.html)
- [`ffi::c_uchar`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_uchar.html)
- [`ffi::c_uint`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_uint.html)
- [`ffi::c_ulong`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_ulong.html)
- [`ffi::c_ulonglong`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_ulonglong.html)
- [`ffi::c_ushort`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_ushort.html)

These APIs are now usable in const contexts:

- [`slice::from_raw_parts`]
  (https://doc.rust-lang.org/stable/core/slice/fn.from_raw_parts.html)

Cargo
-----
- [Packages can now inherit settings from the workspace so that
  the settings can be centralized in one place.]
  (rust-lang/cargo#10859) See
  [`workspace.package`](https://doc.rust-lang.org/nightly/cargo/reference/workspaces.html#the-workspacepackage-table)
  and
  [`workspace.dependencies`](https://doc.rust-lang.org/nightly/cargo/reference/workspaces.html#the-workspacedependencies-table)
  for more details on how to define these common settings.
- [Cargo commands can now accept multiple `--target` flags to build
  for multiple targets at once]
  (rust-lang/cargo#10766), and the
  [`build.target`](https://doc.rust-lang.org/nightly/cargo/reference/config.html#buildtarget)
  config option may now take an array of multiple targets.
- [The `--jobs` argument can now take a negative number to count
  backwards from the max CPUs.]
  (rust-lang/cargo#10844)
- [`cargo add` will now update `Cargo.lock`.]
  (rust-lang/cargo#10902)
- [Added](rust-lang/cargo#10838) the
  [`--crate-type`](https://doc.rust-lang.org/nightly/cargo/commands/cargo-rustc.html#option-cargo-rustc---crate-type)
  flag to `cargo rustc` to override the crate type.
- [Significantly improved the performance fetching git dependencies from GitHub
  when using a hash in the `rev` field.]
  (rust-lang/cargo#10079)

Misc
----
- [The `rust-analyzer` rustup component is now available on the stable channel.]
  (rust-lang/rust#98640)

Compatibility Notes
-------------------
- The minimum required versions for all `-linux-gnu` targets are
  now at least kernel 3.2 and glibc 2.17, for targets that previously
  supported older versions: [Increase the minimum linux-gnu
  versions](rust-lang/rust#95026)
- [Network primitives are now implemented with the ideal Rust
  layout, not the C system layout]
  (rust-lang/rust#78802). This can
  cause problems when transmuting the types.
- [Add assertion that `transmute_copy`'s `U` is not larger than `T`]
  (rust-lang/rust#98839)
- [A soundness bug in `BTreeMap` was fixed]
  (rust-lang/rust#99413) that allowed data
  it was borrowing to be dropped before the container.
- [The Drop behavior of C-like enums cast to ints has changed]
  (rust-lang/rust#96862). These are already
  discouraged by a compiler warning.
- [Relate late-bound closure lifetimes to parent fn in NLL]
  (rust-lang/rust#98835)
- [Errors at const-eval time are now in future incompatibility reports]
  (rust-lang/rust#97743)
- On the `thumbv6m-none-eabi` target, some incorrect `asm!` statements
  were erroneously accepted if they used the high registers (r8 to
  r14) as an input/output operand. [This is no longer accepted]
  (rust-lang/rust#99155).
- [`impl Trait` was accidentally accepted as the associated type
  value of return-position `impl Trait`]
  (rust-lang/rust#97346), without
  fulfilling all the trait bounds of that associated type, as long
  as the hidden type satisfies said bounds. This has been fixed.

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

These changes do not affect any public interfaces of Rust, but they
represent significant improvements to the performance or internals
of rustc and related tools.

- Windows builds now use profile-guided optimization, providing
  10-20% improvements to compiler performance: [Utilize PGO for
  windows x64 rustc dist builds]
  (rust-lang/rust#96978)
- [Stop keeping metadata in memory before writing it to disk]
  (rust-lang/rust#96544)
- [compiletest: strip debuginfo by default for mode=ui]
  (rust-lang/rust#98140)
- Many improvements to generated code for derives, including
  performance improvements:
  - [Don't use match-destructuring for derived ops on structs.]
    (rust-lang/rust#98446)
  - [Many small deriving cleanups]
    (rust-lang/rust#98741)
  - [More derive output improvements]
    (rust-lang/rust#98758)
  - [Clarify deriving code](rust-lang/rust#98915)
  - [Final derive output improvements]
    (rust-lang/rust#99046)
  - [Stop injecting `#[allow(unused_qualifications)]` in generated
    `derive` implementations](rust-lang/rust#99485)
  - [Improve `derive(Debug)`](rust-lang/rust#98190)
- [Bump to clap 3](rust-lang/rust#98213)
- [fully move dropck to mir](rust-lang/rust#98641)
- [Optimize `Vec::insert` for the case where `index == len`.]
  (rust-lang/rust#98755)
- [Convert rust-analyzer to an in-tree tool]
  (rust-lang/rust#99603)
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Nov 16, 2022
Pkgsrc changes:
 * This package now contains rust-analyzer, so implicitly
   conflicts with that pkgsrc package.  The same goes for
   the rust-src package.
 * Add NetBSD/arm6 port
 * Add unfinished NetBSD/mipsel port
 * Revert the use of the internal LLVM,
   should now build with the new pkgsrc LLVM (15).
 * Add depndence on compat80 for sparc64 to fix the build
 * Adapt patches
 * Add CHECK_INTERPRETER_SKIP for a few (mostly unused) files.
   (A proper fix may come later.)

Upstream changes:

Version 1.64.0 (2022-09-22)
===========================

Language
--------
- [Unions with mutable references or tuples of allowed types are
  now allowed](rust-lang/rust#97995)

- It is now considered valid to deallocate memory pointed to by a
  shared reference `&T` [if every byte in `T` is inside an
  `UnsafeCell`](rust-lang/rust#98017)

- Unused tuple struct fields are now warned against in an
  allow-by-default lint, [`unused_tuple_struct_fields`]
  (rust-lang/rust#95977), similar to the
  existing warning for unused struct fields. This lint will become
  warn-by-default in the future.

Compiler
--------
- [Add Nintendo Switch as tier 3 target]
  (rust-lang/rust#88991)
  - Refer to Rust's [platform support page][platform-support-doc] for more
    information on Rust's tiered platform support.
- [Only compile `#[used]` as llvm.compiler.used for ELF targets]
  (rust-lang/rust#93718)
- [Add the `--diagnostic-width` compiler flag to define the terminal width.]
  (rust-lang/rust#95635)
- [Add support for link-flavor `rust-lld` for iOS, tvOS and watchOS]
  (rust-lang/rust#98771)

Libraries
---------
- [Remove restrictions on compare-exchange memory ordering.]
  (rust-lang/rust#98383)
- You can now `write!` or `writeln!` into an `OsString`: [Implement
  `fmt::Write` for `OsString`](rust-lang/rust#97915)
- [Make RwLockReadGuard covariant]
  (rust-lang/rust#96820)
- [Implement `FusedIterator` for `std::net::[Into]Incoming`]
  (rust-lang/rust#97300)
- [`impl<T: AsRawFd> AsRawFd for {Arc,Box}<T>`]
  (rust-lang/rust#97437)
- [`ptr::copy` and `ptr::swap` are doing untyped copies]
  (rust-lang/rust#97712)
- [Add cgroupv1 support to `available_parallelism`]
  (rust-lang/rust#97925)
- [Mitigate many incorrect uses of `mem::uninitialized`]
  (rust-lang/rust#99182)

Stabilized APIs
---------------
- [`future::IntoFuture`]
  (https://doc.rust-lang.org/stable/std/future/trait.IntoFuture.html)
- [`future::poll_fn`]
  (https://doc.rust-lang.org/stable/std/future/fn.poll_fn.html)
- [`task::ready!`]
  (https://doc.rust-lang.org/stable/std/task/macro.ready.html)
- [`num::NonZero*::checked_mul`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.checked_mul)
- [`num::NonZero*::checked_pow`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.checked_pow)
- [`num::NonZero*::saturating_mul`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.saturating_mul)
- [`num::NonZero*::saturating_pow`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.saturating_pow)
- [`num::NonZeroI*::abs`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.abs)
- [`num::NonZeroI*::checked_abs`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.checked_abs)
- [`num::NonZeroI*::overflowing_abs`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.overflowing_abs)
- [`num::NonZeroI*::saturating_abs`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.saturating_abs)
- [`num::NonZeroI*::unsigned_abs`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.unsigned_abs)
- [`num::NonZeroI*::wrapping_abs`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.wrapping_abs)
- [`num::NonZeroU*::checked_add`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.checked_add)
- [`num::NonZeroU*::checked_next_power_of_two`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.checked_next_power_of_two)
- [`num::NonZeroU*::saturating_add`]
  (https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.saturating_add)
- [`os::unix::process::CommandExt::process_group`]
  (https://doc.rust-lang.org/stable/std/os/unix/process/trait.CommandExt.html#tymethod.process_group)
- [`os::windows::fs::FileTypeExt::is_symlink_dir`]
  (https://doc.rust-lang.org/stable/std/os/windows/fs/trait.FileTypeExt.html#tymethod.is_symlink_dir)
- [`os::windows::fs::FileTypeExt::is_symlink_file`]
  (https://doc.rust-lang.org/stable/std/os/windows/fs/trait.FileTypeExt.html#tymethod.is_symlink_file)

These types were previously stable in `std::ffi`, but are now also
available in `core` and `alloc`:

- [`core::ffi::CStr`]
  (https://doc.rust-lang.org/stable/core/ffi/struct.CStr.html)
- [`core::ffi::FromBytesWithNulError`]
  (https://doc.rust-lang.org/stable/core/ffi/struct.FromBytesWithNulError.html)
- [`alloc::ffi::CString`]
  (https://doc.rust-lang.org/stable/alloc/ffi/struct.CString.html)
- [`alloc::ffi::FromVecWithNulError`]
  (https://doc.rust-lang.org/stable/alloc/ffi/struct.FromVecWithNulError.html)
- [`alloc::ffi::IntoStringError`]
  (https://doc.rust-lang.org/stable/alloc/ffi/struct.IntoStringError.html)
- [`alloc::ffi::NulError`]
  (https://doc.rust-lang.org/stable/alloc/ffi/struct.NulError.html)

These types were previously stable in `std::os::raw`, but are now
also available in `core::ffi` and `std::ffi`:

- [`ffi::c_char`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_char.html)
- [`ffi::c_double`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_double.html)
- [`ffi::c_float`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_float.html)
- [`ffi::c_int`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_int.html)
- [`ffi::c_long`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_long.html)
- [`ffi::c_longlong`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_longlong.html)
- [`ffi::c_schar`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_schar.html)
- [`ffi::c_short`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_short.html)
- [`ffi::c_uchar`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_uchar.html)
- [`ffi::c_uint`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_uint.html)
- [`ffi::c_ulong`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_ulong.html)
- [`ffi::c_ulonglong`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_ulonglong.html)
- [`ffi::c_ushort`]
  (https://doc.rust-lang.org/stable/std/ffi/type.c_ushort.html)

These APIs are now usable in const contexts:

- [`slice::from_raw_parts`]
  (https://doc.rust-lang.org/stable/core/slice/fn.from_raw_parts.html)

Cargo
-----
- [Packages can now inherit settings from the workspace so that
  the settings can be centralized in one place.]
  (rust-lang/cargo#10859) See
  [`workspace.package`](https://doc.rust-lang.org/nightly/cargo/reference/workspaces.html#the-workspacepackage-table)
  and
  [`workspace.dependencies`](https://doc.rust-lang.org/nightly/cargo/reference/workspaces.html#the-workspacedependencies-table)
  for more details on how to define these common settings.
- [Cargo commands can now accept multiple `--target` flags to build
  for multiple targets at once]
  (rust-lang/cargo#10766), and the
  [`build.target`](https://doc.rust-lang.org/nightly/cargo/reference/config.html#buildtarget)
  config option may now take an array of multiple targets.
- [The `--jobs` argument can now take a negative number to count
  backwards from the max CPUs.]
  (rust-lang/cargo#10844)
- [`cargo add` will now update `Cargo.lock`.]
  (rust-lang/cargo#10902)
- [Added](rust-lang/cargo#10838) the
  [`--crate-type`](https://doc.rust-lang.org/nightly/cargo/commands/cargo-rustc.html#option-cargo-rustc---crate-type)
  flag to `cargo rustc` to override the crate type.
- [Significantly improved the performance fetching git dependencies from GitHub
  when using a hash in the `rev` field.]
  (rust-lang/cargo#10079)

Misc
----
- [The `rust-analyzer` rustup component is now available on the stable channel.]
  (rust-lang/rust#98640)

Compatibility Notes
-------------------
- The minimum required versions for all `-linux-gnu` targets are
  now at least kernel 3.2 and glibc 2.17, for targets that previously
  supported older versions: [Increase the minimum linux-gnu
  versions](rust-lang/rust#95026)
- [Network primitives are now implemented with the ideal Rust
  layout, not the C system layout]
  (rust-lang/rust#78802). This can
  cause problems when transmuting the types.
- [Add assertion that `transmute_copy`'s `U` is not larger than `T`]
  (rust-lang/rust#98839)
- [A soundness bug in `BTreeMap` was fixed]
  (rust-lang/rust#99413) that allowed data
  it was borrowing to be dropped before the container.
- [The Drop behavior of C-like enums cast to ints has changed]
  (rust-lang/rust#96862). These are already
  discouraged by a compiler warning.
- [Relate late-bound closure lifetimes to parent fn in NLL]
  (rust-lang/rust#98835)
- [Errors at const-eval time are now in future incompatibility reports]
  (rust-lang/rust#97743)
- On the `thumbv6m-none-eabi` target, some incorrect `asm!` statements
  were erroneously accepted if they used the high registers (r8 to
  r14) as an input/output operand. [This is no longer accepted]
  (rust-lang/rust#99155).
- [`impl Trait` was accidentally accepted as the associated type
  value of return-position `impl Trait`]
  (rust-lang/rust#97346), without
  fulfilling all the trait bounds of that associated type, as long
  as the hidden type satisfies said bounds. This has been fixed.

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

These changes do not affect any public interfaces of Rust, but they
represent significant improvements to the performance or internals
of rustc and related tools.

- Windows builds now use profile-guided optimization, providing
  10-20% improvements to compiler performance: [Utilize PGO for
  windows x64 rustc dist builds]
  (rust-lang/rust#96978)
- [Stop keeping metadata in memory before writing it to disk]
  (rust-lang/rust#96544)
- [compiletest: strip debuginfo by default for mode=ui]
  (rust-lang/rust#98140)
- Many improvements to generated code for derives, including
  performance improvements:
  - [Don't use match-destructuring for derived ops on structs.]
    (rust-lang/rust#98446)
  - [Many small deriving cleanups]
    (rust-lang/rust#98741)
  - [More derive output improvements]
    (rust-lang/rust#98758)
  - [Clarify deriving code](rust-lang/rust#98915)
  - [Final derive output improvements]
    (rust-lang/rust#99046)
  - [Stop injecting `#[allow(unused_qualifications)]` in generated
    `derive` implementations](rust-lang/rust#99485)
  - [Improve `derive(Debug)`](rust-lang/rust#98190)
- [Bump to clap 3](rust-lang/rust#98213)
- [fully move dropck to mir](rust-lang/rust#98641)
- [Optimize `Vec::insert` for the case where `index == len`.]
  (rust-lang/rust#98755)
- [Convert rust-analyzer to an in-tree tool]
  (rust-lang/rust#99603)
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. merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make RwLockReadGuard covariant over its type parameter