From 050d5f64e6d3a97d2685b7c6ba05a921ebb31fc2 Mon Sep 17 00:00:00 2001 From: Alex Saveau Date: Sat, 29 Oct 2022 22:56:51 -0700 Subject: [PATCH 01/50] Add BorrowedBuf::filled_mut Signed-off-by: Alex Saveau --- library/std/src/io/readbuf.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs index 4800eeda022..1f3f80b9618 100644 --- a/library/std/src/io/readbuf.rs +++ b/library/std/src/io/readbuf.rs @@ -99,6 +99,13 @@ impl<'data> BorrowedBuf<'data> { unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.filled]) } } + /// Returns a mutable reference to the filled portion of the buffer. + #[inline] + pub fn filled_mut(&mut self) -> &mut [u8] { + // SAFETY: We only slice the filled part of the buffer, which is always valid + unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[0..self.filled]) } + } + /// Returns a cursor over the unfilled part of the buffer. #[inline] pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this> { From 9fc2da1b5438728e9f6469db227a7de2b345203e Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Sat, 31 Dec 2022 01:38:37 +0100 Subject: [PATCH 02/50] Forward `io::{Read,Seek,Write}` impls of `File` to `&File` This reduces code duplication. --- library/std/src/fs.rs | 111 +++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 62 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 89dfdfafdb1..f5848bf4cc4 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -742,78 +742,20 @@ fn buffer_capacity_required(mut file: &File) -> Option { Some(size.saturating_sub(pos) as usize) } -#[stable(feature = "rust1", since = "1.0.0")] -impl Read for File { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.inner.read(buf) - } - - fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - self.inner.read_vectored(bufs) - } - - fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { - self.inner.read_buf(cursor) - } - - #[inline] - fn is_read_vectored(&self) -> bool { - self.inner.is_read_vectored() - } - - // Reserves space in the buffer based on the file size when available. - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - let size = buffer_capacity_required(self); - buf.reserve(size.unwrap_or(0)); - io::default_read_to_end(self, buf, size) - } - - // Reserves space in the buffer based on the file size when available. - fn read_to_string(&mut self, buf: &mut String) -> io::Result { - let size = buffer_capacity_required(self); - buf.reserve(size.unwrap_or(0)); - io::default_read_to_string(self, buf, size) - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl Write for File { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.inner.write(buf) - } - - fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { - self.inner.write_vectored(bufs) - } - - #[inline] - fn is_write_vectored(&self) -> bool { - self.inner.is_write_vectored() - } - - fn flush(&mut self) -> io::Result<()> { - self.inner.flush() - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl Seek for File { - fn seek(&mut self, pos: SeekFrom) -> io::Result { - self.inner.seek(pos) - } -} #[stable(feature = "rust1", since = "1.0.0")] impl Read for &File { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } - fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { - self.inner.read_buf(cursor) - } - fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { self.inner.read_vectored(bufs) } + fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + self.inner.read_buf(cursor) + } + #[inline] fn is_read_vectored(&self) -> bool { self.inner.is_read_vectored() @@ -859,6 +801,51 @@ impl Seek for &File { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl Read for File { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + (&*self).read(buf) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { + (&*self).read_vectored(bufs) + } + fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + (&*self).read_buf(cursor) + } + #[inline] + fn is_read_vectored(&self) -> bool { + (&&*self).is_read_vectored() + } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + (&*self).read_to_end(buf) + } + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + (&*self).read_to_string(buf) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Write for File { + fn write(&mut self, buf: &[u8]) -> io::Result { + (&*self).write(buf) + } + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { + (&*self).write_vectored(bufs) + } + #[inline] + fn is_write_vectored(&self) -> bool { + (&&*self).is_write_vectored() + } + fn flush(&mut self) -> io::Result<()> { + (&*self).flush() + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Seek for File { + fn seek(&mut self, pos: SeekFrom) -> io::Result { + (&*self).seek(pos) + } +} + impl OpenOptions { /// Creates a blank new set of options ready for configuration. /// From 11fecf619aabd1f3d9a015b925bf0deedc7092e9 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Sat, 31 Dec 2022 01:43:54 +0100 Subject: [PATCH 03/50] Add `Read`, `Write` and `Seek` impls for `Arc` where appropriate If `&T` implements these traits, `Arc` has no reason not to do so either. This is useful for operating system handles like `File` or `TcpStream` which don't need a mutable reference to implement these traits. CC #53835. CC #94744. --- library/std/src/fs.rs | 46 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index f5848bf4cc4..901426c5a1c 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -16,6 +16,7 @@ use crate::fmt; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; use crate::path::{Path, PathBuf}; use crate::sealed::Sealed; +use crate::sync::Arc; use crate::sys::fs as fs_imp; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; use crate::time::SystemTime; @@ -846,6 +847,51 @@ impl Seek for File { } } +#[stable(feature = "io_traits_arc", since = "CURRENT_RUSTC_VERSION")] +impl Read for Arc { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + (&**self).read(buf) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { + (&**self).read_vectored(bufs) + } + fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + (&**self).read_buf(cursor) + } + #[inline] + fn is_read_vectored(&self) -> bool { + (&**self).is_read_vectored() + } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + (&**self).read_to_end(buf) + } + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + (&**self).read_to_string(buf) + } +} +#[stable(feature = "io_traits_arc", since = "CURRENT_RUSTC_VERSION")] +impl Write for Arc { + fn write(&mut self, buf: &[u8]) -> io::Result { + (&**self).write(buf) + } + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { + (&**self).write_vectored(bufs) + } + #[inline] + fn is_write_vectored(&self) -> bool { + (&**self).is_write_vectored() + } + fn flush(&mut self) -> io::Result<()> { + (&**self).flush() + } +} +#[stable(feature = "io_traits_arc", since = "CURRENT_RUSTC_VERSION")] +impl Seek for Arc { + fn seek(&mut self, pos: SeekFrom) -> io::Result { + (&**self).seek(pos) + } +} + impl OpenOptions { /// Creates a blank new set of options ready for configuration. /// From 6b214bbc1128aa6bd9ddf732396fda7230dfeb64 Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Thu, 29 Jun 2023 15:01:39 -0700 Subject: [PATCH 04/50] Enable co-induction support for Safe Transmute This patch adds the `#[rustc_coinductive]` annotation to `BikeshedIntrinsicFrom`, so that it's possible to compute transmutability for recursive types. --- library/core/src/mem/transmutability.rs | 1 + .../recursive-wrapper-types-bit-compatible.rs | 5 ++-- ...ursive-wrapper-types-bit-compatible.stderr | 25 ------------------- .../references/recursive-wrapper-types.rs | 5 ++-- .../references/recursive-wrapper-types.stderr | 25 ------------------- 5 files changed, 5 insertions(+), 56 deletions(-) delete mode 100644 tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.stderr delete mode 100644 tests/ui/transmutability/references/recursive-wrapper-types.stderr diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs index 3805d149b70..aed23119fd2 100644 --- a/library/core/src/mem/transmutability.rs +++ b/library/core/src/mem/transmutability.rs @@ -9,6 +9,7 @@ use crate::marker::ConstParamTy; #[lang = "transmute_trait"] #[cfg_attr(not(bootstrap), rustc_deny_explicit_impl(implement_via_object = false))] #[cfg_attr(bootstrap, rustc_deny_explicit_impl)] +#[rustc_coinductive] pub unsafe trait BikeshedIntrinsicFrom where Src: ?Sized, diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs index 3ea80173afa..709d8cdc762 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs +++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs @@ -1,5 +1,4 @@ -// check-fail -// FIXME(bryangarza): Change to check-pass when coinduction is supported for BikeshedIntrinsicFrom +// check-pass #![feature(transmutability)] mod assert { @@ -22,5 +21,5 @@ mod assert { fn main() { #[repr(C)] struct A(bool, &'static A); #[repr(C)] struct B(u8, &'static B); - assert::is_maybe_transmutable::<&'static A, &'static B>(); //~ ERROR overflow evaluating the requirement + assert::is_maybe_transmutable::<&'static A, &'static B>(); } diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.stderr b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.stderr deleted file mode 100644 index fae332e6af9..00000000000 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0275]: overflow evaluating the requirement `B: BikeshedIntrinsicFrom` - --> $DIR/recursive-wrapper-types-bit-compatible.rs:25:5 - | -LL | assert::is_maybe_transmutable::<&'static A, &'static B>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: required by a bound in `is_maybe_transmutable` - --> $DIR/recursive-wrapper-types-bit-compatible.rs:11:14 - | -LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function -LL | where -LL | Dst: BikeshedIntrinsicFrom - | |__________^ required by this bound in `is_maybe_transmutable` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/transmutability/references/recursive-wrapper-types.rs b/tests/ui/transmutability/references/recursive-wrapper-types.rs index 59d1ad84a5d..090c1fea6db 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types.rs +++ b/tests/ui/transmutability/references/recursive-wrapper-types.rs @@ -1,5 +1,4 @@ -// check-fail -// FIXME(bryangarza): Change to check-pass when coinduction is supported for BikeshedIntrinsicFrom +// check-pass #![feature(transmutability)] mod assert { @@ -22,6 +21,6 @@ mod assert { fn main() { #[repr(C)] struct A(&'static B); #[repr(C)] struct B(&'static A); - assert::is_maybe_transmutable::<&'static A, &'static B>(); //~ overflow evaluating the requirement + assert::is_maybe_transmutable::<&'static A, &'static B>(); assert::is_maybe_transmutable::<&'static B, &'static A>(); } diff --git a/tests/ui/transmutability/references/recursive-wrapper-types.stderr b/tests/ui/transmutability/references/recursive-wrapper-types.stderr deleted file mode 100644 index 35a60c22643..00000000000 --- a/tests/ui/transmutability/references/recursive-wrapper-types.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0275]: overflow evaluating the requirement `A: BikeshedIntrinsicFrom` - --> $DIR/recursive-wrapper-types.rs:25:5 - | -LL | assert::is_maybe_transmutable::<&'static A, &'static B>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: required by a bound in `is_maybe_transmutable` - --> $DIR/recursive-wrapper-types.rs:11:14 - | -LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function -LL | where -LL | Dst: BikeshedIntrinsicFrom - | |__________^ required by this bound in `is_maybe_transmutable` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0275`. From 1e377c16fe93b893056bb1d661e16453bd2f7d24 Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 17 May 2023 16:49:18 +0200 Subject: [PATCH 05/50] Add diagnostic items for `<*mut _>::is_null` and `<*const _>::is_null` --- compiler/rustc_span/src/symbol.rs | 2 ++ library/core/src/ptr/const_ptr.rs | 1 + library/core/src/ptr/mut_ptr.rs | 1 + 3 files changed, 4 insertions(+) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c58d85b99f7..95702a5e3cd 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1151,8 +1151,10 @@ symbols! { profiler_runtime, ptr, ptr_cast_mut, + ptr_const_is_null, ptr_from_ref, ptr_guaranteed_cmp, + ptr_is_null, ptr_mask, ptr_null, ptr_null_mut, diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 926189a17b2..74046a9c7c3 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -30,6 +30,7 @@ impl *const T { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] + #[rustc_diagnostic_item = "ptr_const_is_null"] #[inline] pub const fn is_null(self) -> bool { #[inline] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index c6f43857887..e7f27439540 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -29,6 +29,7 @@ impl *mut T { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] + #[rustc_diagnostic_item = "ptr_is_null"] #[inline] pub const fn is_null(self) -> bool { #[inline] From d1c9696b7dd791a64486bc20a689952086a3d5cd Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Tue, 4 Jul 2023 00:39:30 -0700 Subject: [PATCH 06/50] bring back un_derefer and rewrite it again --- .../src/type_check/liveness/polonius.rs | 4 +- compiler/rustc_mir_dataflow/src/impls/mod.rs | 8 +- compiler/rustc_mir_dataflow/src/lib.rs | 1 + .../src/move_paths/builder.rs | 117 +++++++++--------- .../rustc_mir_dataflow/src/move_paths/mod.rs | 58 ++------- compiler/rustc_mir_dataflow/src/un_derefer.rs | 36 ++++++ 6 files changed, 112 insertions(+), 112 deletions(-) create mode 100644 compiler/rustc_mir_dataflow/src/un_derefer.rs diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs index b344ab46adb..012075d7114 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs @@ -20,7 +20,7 @@ struct UseFactsExtractor<'me, 'tcx> { } // A Visitor to walk through the MIR and extract point-wise facts -impl UseFactsExtractor<'_, '_> { +impl<'tcx> UseFactsExtractor<'_, 'tcx> { fn location_to_index(&self, location: Location) -> LocationIndex { self.location_table.mid_index(location) } @@ -45,7 +45,7 @@ impl UseFactsExtractor<'_, '_> { self.path_accessed_at_base.push((path, self.location_to_index(location))); } - fn place_to_mpi(&self, place: &Place<'_>) -> Option { + fn place_to_mpi(&self, place: &Place<'tcx>) -> Option { match self.move_data.rev_lookup.find(place.as_ref()) { LookupResult::Exact(mpi) => Some(mpi), LookupResult::Parent(mmpi) => mmpi, diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs index 98cec1c6760..cb74bea724a 100644 --- a/compiler/rustc_mir_dataflow/src/impls/mod.rs +++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs @@ -731,11 +731,11 @@ fn switch_on_enum_discriminant<'mir, 'tcx>( struct OnMutBorrow(F); -impl Visitor<'_> for OnMutBorrow +impl<'tcx, F> Visitor<'tcx> for OnMutBorrow where - F: FnMut(&mir::Place<'_>), + F: FnMut(&mir::Place<'tcx>), { - fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'_>, location: Location) { + fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) { // FIXME: Does `&raw const foo` allow mutation? See #90413. match rvalue { mir::Rvalue::Ref(_, mir::BorrowKind::Mut { .. }, place) @@ -756,7 +756,7 @@ where fn for_each_mut_borrow<'tcx>( mir: &impl MirVisitable<'tcx>, location: Location, - f: impl FnMut(&mir::Place<'_>), + f: impl FnMut(&mir::Place<'tcx>), ) { let mut vis = OnMutBorrow(f); diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index d43446bc5b2..900d438f8d5 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -43,6 +43,7 @@ pub mod impls; pub mod move_paths; pub mod rustc_peek; pub mod storage; +pub mod un_derefer; pub mod value_analysis; fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index dc7e9ab3ce6..537df1588a3 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -4,7 +4,6 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; use smallvec::{smallvec, SmallVec}; -use std::iter; use std::mem; use super::abs_domain::Lift; @@ -55,7 +54,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { }) .collect(), projections: Default::default(), - derefer_sidetable: Default::default(), + un_derefer: Default::default(), }, move_paths, path_map, @@ -100,11 +99,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { /// /// Maybe we should have separate "borrowck" and "moveck" modes. fn move_path_for(&mut self, place: Place<'tcx>) -> Result> { - let deref_chain = self.builder.data.rev_lookup.deref_chain(place.as_ref()); + let data = &mut self.builder.data; debug!("lookup({:?})", place); - let mut base = - self.builder.data.rev_lookup.find_local(deref_chain.first().unwrap_or(&place).local); + let mut base = data.rev_lookup.find_local(place.local); // The move path index of the first union that we find. Once this is // some we stop creating child move paths, since moves from unions @@ -113,55 +111,60 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { // from `*(u.f: &_)` isn't allowed. let mut union_path = None; - for place in deref_chain.into_iter().chain(iter::once(place)) { - for (place_ref, elem) in place.as_ref().iter_projections() { - let body = self.builder.body; - let tcx = self.builder.tcx; - let place_ty = place_ref.ty(body, tcx).ty; - match place_ty.kind() { - ty::Ref(..) | ty::RawPtr(..) => { - return Err(MoveError::cannot_move_out_of( - self.loc, - BorrowedContent { - target_place: place_ref.project_deeper(&[elem], tcx), - }, - )); - } - ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => { - return Err(MoveError::cannot_move_out_of( - self.loc, - InteriorOfTypeWithDestructor { container_ty: place_ty }, - )); - } - ty::Adt(adt, _) if adt.is_union() => { - union_path.get_or_insert(base); - } - ty::Slice(_) => { - return Err(MoveError::cannot_move_out_of( - self.loc, - InteriorOfSliceOrArray { - ty: place_ty, - is_index: matches!(elem, ProjectionElem::Index(..)), - }, - )); - } - - ty::Array(..) => { - if let ProjectionElem::Index(..) = elem { - return Err(MoveError::cannot_move_out_of( - self.loc, - InteriorOfSliceOrArray { ty: place_ty, is_index: true }, - )); - } - } - - _ => {} - }; - - if union_path.is_none() { - base = self - .add_move_path(base, elem, |tcx| place_ref.project_deeper(&[elem], tcx)); + for (place_ref, elem) in data.rev_lookup.un_derefer.iter_projections(place.as_ref()) { + let body = self.builder.body; + let tcx = self.builder.tcx; + let place_ty = place_ref.ty(body, tcx).ty; + match place_ty.kind() { + ty::Ref(..) | ty::RawPtr(..) => { + return Err(MoveError::cannot_move_out_of( + self.loc, + BorrowedContent { target_place: place_ref.project_deeper(&[elem], tcx) }, + )); } + ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => { + return Err(MoveError::cannot_move_out_of( + self.loc, + InteriorOfTypeWithDestructor { container_ty: place_ty }, + )); + } + ty::Adt(adt, _) if adt.is_union() => { + union_path.get_or_insert(base); + } + ty::Slice(_) => { + return Err(MoveError::cannot_move_out_of( + self.loc, + InteriorOfSliceOrArray { + ty: place_ty, + is_index: matches!(elem, ProjectionElem::Index(..)), + }, + )); + } + + ty::Array(..) => { + if let ProjectionElem::Index(..) = elem { + return Err(MoveError::cannot_move_out_of( + self.loc, + InteriorOfSliceOrArray { ty: place_ty, is_index: true }, + )); + } + } + + _ => {} + }; + + if union_path.is_none() { + // inlined from add_move_path because of a borrowck conflict with the iterator + base = + *data.rev_lookup.projections.entry((base, elem.lift())).or_insert_with(|| { + MoveDataBuilder::new_move_path( + &mut data.move_paths, + &mut data.path_map, + &mut data.init_path_map, + Some(base), + place_ref.project_deeper(&[elem], tcx), + ) + }) } } @@ -282,10 +285,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { fn gather_statement(&mut self, stmt: &Statement<'tcx>) { match &stmt.kind { StatementKind::Assign(box (place, Rvalue::CopyForDeref(reffed))) => { - assert!(place.projection.is_empty()); - if self.builder.body.local_decls[place.local].is_deref_temp() { - self.builder.data.rev_lookup.derefer_sidetable.insert(place.local, *reffed); - } + assert!(self.builder.body.local_decls[place.local].is_deref_temp()); + self.builder.data.rev_lookup.un_derefer.insert(place.as_local().unwrap(), *reffed); } StatementKind::Assign(box (place, rval)) => { self.create_move_path(*place); @@ -306,7 +307,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { StatementKind::StorageLive(_) => {} StatementKind::StorageDead(local) => { // DerefTemp locals (results of CopyForDeref) don't actually move anything. - if !self.builder.data.rev_lookup.derefer_sidetable.contains_key(&local) { + if !self.builder.body.local_decls[*local].is_deref_temp() { self.gather_move(Place::from(*local)); } } diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs index aa901f66d3f..0f7da4f46e3 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs @@ -1,4 +1,5 @@ use crate::move_paths::builder::MoveDat; +use crate::un_derefer::UnDerefer; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::*; @@ -300,8 +301,7 @@ pub struct MovePathLookup<'tcx> { /// elem to the associated MovePathIndex. projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex>, - /// Maps `DerefTemp` locals to the `Place`s assigned to them. - derefer_sidetable: FxHashMap>, + un_derefer: UnDerefer<'tcx>, } mod builder; @@ -317,47 +317,24 @@ impl<'tcx> MovePathLookup<'tcx> { // alternative will *not* create a MovePath on the fly for an // unknown place, but will rather return the nearest available // parent. - pub fn find(&self, place: PlaceRef<'_>) -> LookupResult { - let deref_chain = self.deref_chain(place); + pub fn find(&self, place: PlaceRef<'tcx>) -> LookupResult { + let mut result = self.find_local(place.local); - let local = match deref_chain.first() { - Some(place) => place.local, - None => place.local, - }; - - let mut result = *self.locals.get(&local).unwrap_or_else(|| { - bug!("base local ({local:?}) of deref_chain should not be a deref temp") - }); - - // this needs to be a closure because `place` has a different lifetime than `prefix`'s places - let mut subpaths_for_place = |place: PlaceRef<'_>| { - for elem in place.projection.iter() { - if let Some(&subpath) = self.projections.get(&(result, elem.lift())) { - result = subpath; - } else { - return Some(result); - } - } - None - }; - - for place in deref_chain { - if let Some(result) = subpaths_for_place(place.as_ref()) { + for (_, elem) in self.un_derefer.iter_projections(place) { + if let Some(&subpath) = self.projections.get(&(result, elem.lift())) { + result = subpath; + } else { return LookupResult::Parent(Some(result)); } } - if let Some(result) = subpaths_for_place(place) { - return LookupResult::Parent(Some(result)); - } - LookupResult::Exact(result) } pub fn find_local(&self, local: Local) -> MovePathIndex { - let deref_chain = self.deref_chain(Place::from(local).as_ref()); + let deref_chain = self.un_derefer.deref_chain(local); - let local = match deref_chain.last() { + let local = match deref_chain.first() { Some(place) => place.local, None => local, }; @@ -374,21 +351,6 @@ impl<'tcx> MovePathLookup<'tcx> { ) -> impl DoubleEndedIterator + ExactSizeIterator + '_ { self.locals.iter().map(|(&l, &idx)| (l, idx)) } - - /// Returns the chain of places behind `DerefTemp` locals in `place` - pub fn deref_chain(&self, place: PlaceRef<'_>) -> Vec> { - let mut prefix = Vec::new(); - let mut local = place.local; - - while let Some(&reffed) = self.derefer_sidetable.get(&local) { - prefix.insert(0, reffed); - local = reffed.local; - } - - debug!("deref_chain({place:?}) = {prefix:?}"); - - prefix - } } #[derive(Debug)] diff --git a/compiler/rustc_mir_dataflow/src/un_derefer.rs b/compiler/rustc_mir_dataflow/src/un_derefer.rs new file mode 100644 index 00000000000..fdd2eb0233d --- /dev/null +++ b/compiler/rustc_mir_dataflow/src/un_derefer.rs @@ -0,0 +1,36 @@ +use rustc_data_structures::fx::FxHashMap; +use rustc_middle::mir::*; + +use std::iter::once; + +/// Used for reverting changes made by `DerefSeparator` +#[derive(Default, Debug)] +pub struct UnDerefer<'tcx> { + deref_chains: FxHashMap>>, +} + +impl<'tcx> UnDerefer<'tcx> { + pub fn insert(&mut self, local: Local, reffed: Place<'tcx>) { + let mut chain = self.deref_chains.remove(&reffed.local).unwrap_or_default(); + chain.push(reffed); + self.deref_chains.insert(local, chain); + } + + /// Returns the chain of places behind `DerefTemp` locals + pub fn deref_chain(&self, local: Local) -> &[Place<'tcx>] { + self.deref_chains.get(&local).map(Vec::as_slice).unwrap_or_default() + } + + pub fn iter_projections( + &self, + place: PlaceRef<'tcx>, + ) -> impl Iterator, PlaceElem<'tcx>)> + DoubleEndedIterator + '_ { + let deref_chain = self.deref_chain(place.local); + + deref_chain + .iter() + .map(Place::as_ref) + .chain(once(place)) + .flat_map(|place| place.iter_projections()) + } +} From e153d82c76a9749c91e6d50ff01636f0dbee0f14 Mon Sep 17 00:00:00 2001 From: jyn Date: Sat, 3 Jun 2023 13:09:01 -0500 Subject: [PATCH 07/50] Make `--dry-run` more useful when download-rustc is enabled Previously, it would always treat download-rustc as set to false, which made bootstrap issues with download-rustc hard to debug. --- src/bootstrap/config.rs | 4 ++-- src/bootstrap/download.rs | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 5f5f7ea25fb..2320661bd03 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -1813,11 +1813,11 @@ impl Config { self.download_rustc_commit().is_some() } - pub(crate) fn download_rustc_commit(&self) -> Option<&'static str> { + pub(crate) fn download_rustc_commit(&self) -> Option<&str> { static DOWNLOAD_RUSTC: OnceCell> = OnceCell::new(); if self.dry_run() && DOWNLOAD_RUSTC.get().is_none() { // avoid trying to actually download the commit - return None; + return self.download_rustc_commit.as_deref(); } DOWNLOAD_RUSTC diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs index cb40521dda7..fbb97a1ba6d 100644 --- a/src/bootstrap/download.rs +++ b/src/bootstrap/download.rs @@ -402,6 +402,10 @@ impl Config { fn ci_component_contents(&self, stamp_file: &str) -> Vec { assert!(self.download_rustc()); + if self.dry_run() { + return vec![]; + } + let ci_rustc_dir = self.out.join(&*self.build.triple).join("ci-rustc"); let stamp_file = ci_rustc_dir.join(stamp_file); let contents_file = t!(File::open(&stamp_file), stamp_file.display().to_string()); From 32057b7ec369e39424798f213c95ac9406f76786 Mon Sep 17 00:00:00 2001 From: jyn Date: Thu, 25 May 2023 21:35:55 -0500 Subject: [PATCH 08/50] check ci-rustc options --- src/bootstrap/config.rs | 42 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 2320661bd03..a16f762b2fb 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -39,6 +39,16 @@ macro_rules! check_ci_llvm { }; } +macro_rules! check_ci_rustc { + ($name:expr) => { + assert!( + $name.is_none(), + "setting {} is incompatible with download-ci-rustc.", + stringify!($name) + ); + }; +} + #[derive(Clone, Default)] pub enum DryRun { /// This isn't a dry run. @@ -1328,6 +1338,25 @@ impl Config { let mut omit_git_hash = None; if let Some(rust) = toml.rust { + set(&mut config.channel, rust.channel); + + config.download_rustc_commit = config.download_ci_rustc_commit(rust.download_rustc); + // This list is incomplete, please help by expanding it! + if config.download_rustc_commit.is_some() { + // We need the channel used by the downloaded compiler to match the one we set for rustdoc; + // otherwise rustdoc-ui tests break. + let ci_channel = t!(fs::read_to_string(config.src.join("src/ci/channel"))); + let ci_channel = ci_channel.trim_end(); + if config.channel != ci_channel + && !(config.channel == "dev" && ci_channel == "nightly") + { + panic!( + "setting rust.channel={} is incompatible with download-rustc", + config.channel + ); + } + } + debug = rust.debug; debug_assertions = rust.debug_assertions; debug_assertions_std = rust.debug_assertions_std; @@ -1339,6 +1368,7 @@ impl Config { debuginfo_level_std = rust.debuginfo_level_std; debuginfo_level_tools = rust.debuginfo_level_tools; debuginfo_level_tests = rust.debuginfo_level_tests; + config.rust_split_debuginfo = rust .split_debuginfo .as_deref() @@ -1354,7 +1384,6 @@ impl Config { set(&mut config.jemalloc, rust.jemalloc); set(&mut config.test_compare_mode, rust.test_compare_mode); set(&mut config.backtrace, rust.backtrace); - set(&mut config.channel, rust.channel); config.description = rust.description; set(&mut config.rust_dist_src, rust.dist_src); set(&mut config.verbose_tests, rust.verbose_tests); @@ -1395,8 +1424,6 @@ impl Config { config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config); config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use); config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate); - config.download_rustc_commit = config.download_ci_rustc_commit(rust.download_rustc); - config.rust_lto = rust .lto .as_deref() @@ -1491,6 +1518,10 @@ impl Config { check_ci_llvm!(llvm.plugins); } + if config.download_rustc_commit.is_some() { + check_ci_rustc!(llvm.assertions); + } + // NOTE: can never be hit when downloading from CI, since we call `check_ci_llvm!(thin_lto)` above. if config.llvm_thin_lto && llvm.link_shared.is_none() { // If we're building with ThinLTO on, by default we want to link @@ -1508,6 +1539,11 @@ impl Config { let mut target = Target::from_triple(&triple); if let Some(ref s) = cfg.llvm_config { + if config.download_rustc_commit.is_some() && triple == &*config.build.triple { + panic!( + "setting llvm_config for the host is incompatible with download-rustc" + ); + } target.llvm_config = Some(config.src.join(s)); } target.llvm_has_rust_patches = cfg.llvm_has_rust_patches; From 1f0487faec16c663c23010fe641b26ee5deb9387 Mon Sep 17 00:00:00 2001 From: jyn Date: Sat, 3 Jun 2023 14:01:45 -0500 Subject: [PATCH 09/50] fix `x test --stage 0 core` --- src/bootstrap/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index e4cc88c64a5..ec7b9357b5a 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -2344,7 +2344,7 @@ impl Step for Crate { // `std_cargo` actually does the wrong thing: it passes `--sysroot build/host/stage2`, // but we want to use the force-recompile std we just built in `build/host/stage2-test-sysroot`. // Override it. - if builder.download_rustc() { + if builder.download_rustc() && compiler.stage > 0 { let sysroot = builder .out .join(compiler.host.triple) From f7287b9a2c3c161f038d3d83bc4e08cbec5d1841 Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 4 Jun 2023 23:22:17 -0500 Subject: [PATCH 10/50] don't try to cross-compile sanitizer tests this was a pre-existing latent bug, we just didn't have any CI builders exercising it. fixes the following errors: ``` ---- [ui] tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs#opt1 stdout ---- error in revision `opt1`: test compilation failed although it shouldn't! status: exit status: 1 command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=i686-unknown-linux-gnu" "--cfg" "opt1" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Cstrip=debuginfo" "--remap-path-prefix=/checkout/tests/ui=fake-test-src-base" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/sanitize/new-llvm-pass-manager-thin-lto.opt1/a" "-A" "unused" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/i686-unknown-linux-gnu/native/rust-test-helpers" "-Clinker=x86_64-linux-gnu-gcc" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/sanitize/new-llvm-pass-manager-thin-lto.opt1/auxiliary" "-Zsanitizer=address" "-Clto=thin" "-Copt-level=1" --- stderr ------------------------------- error: linking with `x86_64-linux-gnu-gcc` failed: exit status: 1 = note: x86_64-linux-gnu-gcc: error: /checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/i686-unknown-linux-gnu/lib/librustc-nightly_rt.asan.a: No such file or directory failures: [ui] tests/ui/sanitize/badfree.rs [ui] tests/ui/sanitize/address.rs [ui] tests/ui/sanitize/use-after-scope.rs [ui] tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs#opt0 [ui] tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs#opt1 ``` --- tests/ui/sanitize/address.rs | 3 ++- tests/ui/sanitize/badfree.rs | 1 + tests/ui/sanitize/issue-72154-lifetime-markers.rs | 1 + tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs | 1 + tests/ui/sanitize/use-after-scope.rs | 1 + 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/ui/sanitize/address.rs b/tests/ui/sanitize/address.rs index 5b2cea87560..1faab1fd2fc 100644 --- a/tests/ui/sanitize/address.rs +++ b/tests/ui/sanitize/address.rs @@ -1,11 +1,12 @@ // needs-sanitizer-support // needs-sanitizer-address +// ignore-cross-compile // // compile-flags: -Z sanitizer=address -O -g // // run-fail // error-pattern: AddressSanitizer: stack-buffer-overflow -// error-pattern: 'xs' (line 13) <== Memory access at offset +// error-pattern: 'xs' (line 14) <== Memory access at offset use std::hint::black_box; diff --git a/tests/ui/sanitize/badfree.rs b/tests/ui/sanitize/badfree.rs index 095a6f4697b..c8d1ce7dff2 100644 --- a/tests/ui/sanitize/badfree.rs +++ b/tests/ui/sanitize/badfree.rs @@ -1,5 +1,6 @@ // needs-sanitizer-support // needs-sanitizer-address +// ignore-cross-compile // // compile-flags: -Z sanitizer=address -O // diff --git a/tests/ui/sanitize/issue-72154-lifetime-markers.rs b/tests/ui/sanitize/issue-72154-lifetime-markers.rs index b2e182238ce..3d9c51daa65 100644 --- a/tests/ui/sanitize/issue-72154-lifetime-markers.rs +++ b/tests/ui/sanitize/issue-72154-lifetime-markers.rs @@ -5,6 +5,7 @@ // // needs-sanitizer-support // needs-sanitizer-address +// ignore-cross-compile // // compile-flags: -Copt-level=0 -Zsanitizer=address // run-pass diff --git a/tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs b/tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs index 33e18e35522..052a40598a8 100644 --- a/tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs +++ b/tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs @@ -4,6 +4,7 @@ // // needs-sanitizer-support // needs-sanitizer-address +// ignore-cross-compile // // no-prefer-dynamic // revisions: opt0 opt1 diff --git a/tests/ui/sanitize/use-after-scope.rs b/tests/ui/sanitize/use-after-scope.rs index 30be2ae6f09..de63eea194b 100644 --- a/tests/ui/sanitize/use-after-scope.rs +++ b/tests/ui/sanitize/use-after-scope.rs @@ -1,5 +1,6 @@ // needs-sanitizer-support // needs-sanitizer-address +// ignore-cross-compile // // compile-flags: -Zsanitizer=address // run-fail From baae59eea3230bdda6b536aaf8df15b9b96c599f Mon Sep 17 00:00:00 2001 From: jyn Date: Sat, 1 Jul 2023 12:03:16 -0500 Subject: [PATCH 11/50] allow mixing `llvm.assertions` and `download-rustc` by using `rustc-builds-alt` if download-rustc is set this also changes the download code to use a separate build/cache/ directory and .rustc-stamp stamp file depending on whether assertions are enabled. --- src/bootstrap/config.rs | 14 -------------- src/bootstrap/download.rs | 30 ++++++++++++++++++++++-------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index a16f762b2fb..af29fe0baae 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -39,16 +39,6 @@ macro_rules! check_ci_llvm { }; } -macro_rules! check_ci_rustc { - ($name:expr) => { - assert!( - $name.is_none(), - "setting {} is incompatible with download-ci-rustc.", - stringify!($name) - ); - }; -} - #[derive(Clone, Default)] pub enum DryRun { /// This isn't a dry run. @@ -1518,10 +1508,6 @@ impl Config { check_ci_llvm!(llvm.plugins); } - if config.download_rustc_commit.is_some() { - check_ci_rustc!(llvm.assertions); - } - // NOTE: can never be hit when downloading from CI, since we call `check_ci_llvm!(thin_lto)` above. if config.llvm_thin_lto && llvm.link_shared.is_none() { // If we're building with ThinLTO on, by default we want to link diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs index fbb97a1ba6d..90578065ba2 100644 --- a/src/bootstrap/download.rs +++ b/src/bootstrap/download.rs @@ -423,7 +423,7 @@ impl Config { self.download_toolchain( &version, "ci-rustc", - commit, + &format!("{commit}-{}", self.llvm_assertions), &extra_components, Self::download_ci_component, ); @@ -499,8 +499,15 @@ impl Config { /// Download a single component of a CI-built toolchain (not necessarily a published nightly). // NOTE: intentionally takes an owned string to avoid downloading multiple times by accident - fn download_ci_component(&self, filename: String, prefix: &str, commit: &str) { - Self::download_component(self, DownloadSource::CI, filename, prefix, commit, "ci-rustc") + fn download_ci_component(&self, filename: String, prefix: &str, commit_with_assertions: &str) { + Self::download_component( + self, + DownloadSource::CI, + filename, + prefix, + commit_with_assertions, + "ci-rustc", + ) } fn download_component( @@ -520,11 +527,18 @@ impl Config { let bin_root = self.out.join(self.build.triple).join(destination); let tarball = cache_dir.join(&filename); let (base_url, url, should_verify) = match mode { - DownloadSource::CI => ( - self.stage0_metadata.config.artifacts_server.clone(), - format!("{key}/{filename}"), - false, - ), + DownloadSource::CI => { + let dist_server = if self.llvm_assertions { + self.stage0_metadata.config.artifacts_with_llvm_assertions_server.clone() + } else { + self.stage0_metadata.config.artifacts_server.clone() + }; + let url = format!( + "{}/{filename}", + key.strip_suffix(&format!("-{}", self.llvm_assertions)).unwrap() + ); + (dist_server, url, false) + } DownloadSource::Dist => { let dist_server = env::var("RUSTUP_DIST_SERVER") .unwrap_or(self.stage0_metadata.config.dist_server.to_string()); From 24534cffe60044965d3cd11d49e9b568c3dfa865 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 5 Jul 2023 15:33:21 -0700 Subject: [PATCH 12/50] style-guide: Fix chain example to match rustfmt behavior The style guide gave an example of breaking a multi-line chain element and all subsequent elements to a new line, but that same example and the accompanying text also had several chain items stacked on the first line. rustfmt doesn't do this, except when the rule saying to combine ``` shrt .y() ``` into ``` shrt.y() ``` applies. --- src/doc/style-guide/src/expressions.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index f5e37b6c46f..fda3b8e8209 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -450,12 +450,11 @@ foo( #### Multi-line elements -If any element in a chain is formatted across multiple lines, then that element -and any later elements must be on their own line. Earlier elements may be kept -on a single line. E.g., +If any element in a chain is formatted across multiple lines, put that element +and any later elements on their own lines. ```rust -a.b.c()?.d +a.b.c()? .foo( an_expr, another_expr, From ddd5fd1e3cff5e0f1971fb8ba545804ac96652f5 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 5 Jul 2023 15:56:13 -0700 Subject: [PATCH 13/50] style-guide: Expand example of combinable expressions to include arrays Arrays are allowed as combinable expressions, but none of the examples show that. --- src/doc/style-guide/src/expressions.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index f5e37b6c46f..5b07a27c8fc 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -801,6 +801,16 @@ foo(|param| { action(); foo(param) }) + +let x = combinable([ + an_expr, + another_expr, +]); + +let arr = [combinable( + an_expr, + another_expr, +)]; ``` Such behaviour should extend recursively, however, tools may choose to limit the From 3fdb443e4e5ce8f04b818754950ff28537d50d93 Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 6 Jul 2023 10:17:26 +0100 Subject: [PATCH 14/50] Add a new trait to `Debug` things with an infcx available --- compiler/rustc_infer/src/infer/mod.rs | 38 ++++ compiler/rustc_middle/src/ty/consts/kind.rs | 4 +- compiler/rustc_middle/src/ty/list.rs | 11 + compiler/rustc_middle/src/ty/mod.rs | 1 + .../rustc_middle/src/ty/structural_impls.rs | 191 ++++++++++++++++-- compiler/rustc_middle/src/ty/sty.rs | 22 +- compiler/rustc_middle/src/ty/subst.rs | 11 - compiler/rustc_type_ir/src/lib.rs | 41 ++-- .../rustc_type_ir/src/structural_impls.rs | 181 +++++++++++++++-- compiler/rustc_type_ir/src/sty.rs | 79 +++++--- 10 files changed, 474 insertions(+), 105 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index fca32b73d1d..a123effd0f0 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -332,6 +332,39 @@ pub struct InferCtxt<'tcx> { next_trait_solver: bool, } +impl<'tcx> ty::InferCtxtLike> for InferCtxt<'tcx> { + fn universe_of_ty(&self, ty: ty::InferTy) -> Option { + use InferTy::*; + match ty { + // FIXME(BoxyUwU): this is kind of jank and means that printing unresolved + // ty infers will give you the universe of the var it resolved to not the universe + // it actually had. It also means that if you have a `?0.1` and infer it to `u8` then + // try to print out `?0.1` it will just print `?0`. + TyVar(ty_vid) => match self.probe_ty_var(ty_vid) { + Err(universe) => Some(universe), + Ok(_) => None, + }, + IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => None, + } + } + + fn universe_of_ct(&self, ct: ty::InferConst<'tcx>) -> Option { + use ty::InferConst::*; + match ct { + // Same issue as with `universe_of_ty` + Var(ct_vid) => match self.probe_const_var(ct_vid) { + Err(universe) => Some(universe), + Ok(_) => None, + }, + Fresh(_) => None, + } + } + + fn universe_of_lt(&self, lt: ty::RegionVid) -> Option { + Some(self.universe_of_region_vid(lt)) + } +} + /// See the `error_reporting` module for more details. #[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)] pub enum ValuePairs<'tcx> { @@ -1068,6 +1101,11 @@ impl<'tcx> InferCtxt<'tcx> { self.inner.borrow_mut().unwrap_region_constraints().universe(r) } + /// Return the universe that the region variable `r` was created in. + pub fn universe_of_region_vid(&self, vid: ty::RegionVid) -> ty::UniverseIndex { + self.inner.borrow_mut().unwrap_region_constraints().var_universe(vid) + } + /// Number of region variables created so far. pub fn num_region_vars(&self) -> usize { self.inner.borrow_mut().unwrap_region_constraints().num_region_vars() diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index a6bf7491118..5f2b6d42bf8 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -8,7 +8,7 @@ use rustc_hir::def_id::DefId; use rustc_macros::HashStable; /// An unevaluated (potentially generic) constant used in the type-system. -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] +#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] #[derive(Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct UnevaluatedConst<'tcx> { pub def: DefId, @@ -35,7 +35,7 @@ impl<'tcx> UnevaluatedConst<'tcx> { } } -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] #[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] pub enum Expr<'tcx> { Binop(mir::BinOp, Const<'tcx>, Const<'tcx>), diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index 71911a5a618..7a32cfb1085 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -1,6 +1,7 @@ use crate::arena::Arena; use rustc_data_structures::aligned::{align_of, Aligned}; use rustc_serialize::{Encodable, Encoder}; +use rustc_type_ir::{InferCtxtLike, OptWithInfcx}; use std::alloc::Layout; use std::cmp::Ordering; use std::fmt; @@ -119,6 +120,14 @@ impl fmt::Debug for List { (**self).fmt(f) } } +impl<'tcx, T: super::DebugWithInfcx>> super::DebugWithInfcx> for List { + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + fmt::Debug::fmt(&this.map(|this| this.as_slice()), f) + } +} impl> Encodable for List { #[inline] @@ -202,6 +211,8 @@ unsafe impl Sync for List {} // We need this since `List` uses extern type `OpaqueListContents`. #[cfg(parallel_compiler)] use rustc_data_structures::sync::DynSync; + +use super::TyCtxt; #[cfg(parallel_compiler)] unsafe impl DynSync for List {} diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c100c45b61a..4362e4b6838 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -53,6 +53,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ExpnId, ExpnKind, Span}; use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx}; pub use rustc_target::abi::{ReprFlags, ReprOptions}; +pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, OptWithInfcx}; pub use subst::*; pub use vtable::*; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 4a639a2a0fe..85b290b70b2 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -11,13 +11,15 @@ use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; use rustc_hir::def::Namespace; use rustc_index::{Idx, IndexVec}; use rustc_target::abi::TyAndLayout; -use rustc_type_ir::ConstKind; +use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, OptWithInfcx}; -use std::fmt; +use std::fmt::{self, Debug}; use std::ops::ControlFlow; use std::rc::Rc; use std::sync::Arc; +use super::{GenericArg, GenericArgKind, Region}; + impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { @@ -89,7 +91,16 @@ impl fmt::Debug for ty::FreeRegion { impl<'tcx> fmt::Debug for ty::FnSig<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let ty::FnSig { inputs_and_output: _, c_variadic, unsafety, abi } = self; + OptWithInfcx::new_no_ctx(self).fmt(f) + } +} +impl<'tcx> DebugWithInfcx> for ty::FnSig<'tcx> { + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + let sig = this.data; + let ty::FnSig { inputs_and_output: _, c_variadic, unsafety, abi } = sig; write!(f, "{}", unsafety.prefix_str())?; match abi { @@ -98,15 +109,15 @@ impl<'tcx> fmt::Debug for ty::FnSig<'tcx> { }; write!(f, "fn(")?; - let inputs = self.inputs(); + let inputs = sig.inputs(); match inputs.len() { 0 if *c_variadic => write!(f, "...)")?, 0 => write!(f, ")")?, _ => { - for ty in &self.inputs()[0..(self.inputs().len() - 1)] { - write!(f, "{ty:?}, ")?; + for ty in &sig.inputs()[0..(sig.inputs().len() - 1)] { + write!(f, "{:?}, ", &this.wrap(ty))?; } - write!(f, "{:?}", self.inputs().last().unwrap())?; + write!(f, "{:?}", &this.wrap(sig.inputs().last().unwrap()))?; if *c_variadic { write!(f, "...")?; } @@ -114,9 +125,9 @@ impl<'tcx> fmt::Debug for ty::FnSig<'tcx> { } } - match self.output().kind() { + match sig.output().kind() { ty::Tuple(list) if list.is_empty() => Ok(()), - _ => write!(f, " -> {:?}", self.output()), + _ => write!(f, " -> {:?}", &this.wrap(sig.output())), } } } @@ -133,6 +144,14 @@ impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> { } } +impl<'tcx> ty::DebugWithInfcx> for Ty<'tcx> { + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + this.data.fmt(f) + } +} impl<'tcx> fmt::Debug for Ty<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { with_no_trimmed_paths!(fmt::Display::fmt(self, f)) @@ -217,9 +236,17 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { impl<'tcx> fmt::Debug for AliasTy<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + OptWithInfcx::new_no_ctx(self).fmt(f) + } +} +impl<'tcx> DebugWithInfcx> for AliasTy<'tcx> { + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { f.debug_struct("AliasTy") - .field("substs", &self.substs) - .field("def_id", &self.def_id) + .field("substs", &this.map(|data| data.substs)) + .field("def_id", &this.data.def_id) .finish() } } @@ -232,13 +259,93 @@ impl<'tcx> fmt::Debug for ty::InferConst<'tcx> { } } } +impl<'tcx> DebugWithInfcx> for ty::InferConst<'tcx> { + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + use ty::InferConst::*; + match this.infcx.and_then(|infcx| infcx.universe_of_ct(*this.data)) { + None => write!(f, "{:?}", this.data), + Some(universe) => match *this.data { + Var(vid) => write!(f, "?{}_{}c", vid.index, universe.index()), + Fresh(_) => { + unreachable!() + } + }, + } + } +} + +impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + OptWithInfcx::new_no_ctx(self).fmt(f) + } +} +impl<'tcx> DebugWithInfcx> for ty::consts::Expr<'tcx> { + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match this.data { + ty::Expr::Binop(op, lhs, rhs) => { + write!(f, "({op:?}: {:?}, {:?})", &this.wrap(lhs), &this.wrap(rhs)) + } + ty::Expr::UnOp(op, rhs) => write!(f, "({op:?}: {:?})", &this.wrap(rhs)), + ty::Expr::FunctionCall(func, args) => { + write!(f, "{:?}(", &this.wrap(func))?; + for arg in args.as_slice().iter().rev().skip(1).rev() { + write!(f, "{:?}, ", &this.wrap(arg))?; + } + if let Some(arg) = args.last() { + write!(f, "{:?}", &this.wrap(arg))?; + } + + write!(f, ")") + } + ty::Expr::Cast(cast_kind, lhs, rhs) => { + write!(f, "({cast_kind:?}: {:?}, {:?})", &this.wrap(lhs), &this.wrap(rhs)) + } + } + } +} + +impl<'tcx> fmt::Debug for ty::UnevaluatedConst<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + OptWithInfcx::new_no_ctx(self).fmt(f) + } +} +impl<'tcx> DebugWithInfcx> for ty::UnevaluatedConst<'tcx> { + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_struct("UnevaluatedConst") + .field("def", &this.data.def) + .field("substs", &this.wrap(this.data.substs)) + .finish() + } +} impl<'tcx> fmt::Debug for ty::Const<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + OptWithInfcx::new_no_ctx(self).fmt(f) + } +} +impl<'tcx> DebugWithInfcx> for ty::Const<'tcx> { + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { // This reflects what `Const` looked liked before `Interned` was // introduced. We print it like this to avoid having to update expected // output in a lot of tests. - write!(f, "Const {{ ty: {:?}, kind: {:?} }}", self.ty(), self.kind()) + write!( + f, + "Const {{ ty: {:?}, kind: {:?} }}", + &this.map(|data| data.ty()), + &this.map(|data| data.kind()) + ) } } @@ -261,6 +368,66 @@ impl fmt::Debug for ty::Placeholder { } } +impl<'tcx> fmt::Debug for GenericArg<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.unpack() { + GenericArgKind::Lifetime(lt) => lt.fmt(f), + GenericArgKind::Type(ty) => ty.fmt(f), + GenericArgKind::Const(ct) => ct.fmt(f), + } + } +} +impl<'tcx> DebugWithInfcx> for GenericArg<'tcx> { + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match this.data.unpack() { + GenericArgKind::Lifetime(lt) => write!(f, "{:?}", &this.wrap(lt)), + GenericArgKind::Const(ct) => write!(f, "{:?}", &this.wrap(ct)), + GenericArgKind::Type(ty) => write!(f, "{:?}", &this.wrap(ty)), + } + } +} + +impl<'tcx> fmt::Debug for Region<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self.kind()) + } +} +impl<'tcx> DebugWithInfcx> for Region<'tcx> { + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + write!(f, "{:?}", &this.map(|data| data.kind())) + } +} + +impl<'tcx> DebugWithInfcx> for ty::RegionVid { + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match this.infcx.and_then(|infcx| infcx.universe_of_lt(*this.data)) { + Some(universe) => write!(f, "'?{}_{}", this.data.index(), universe.index()), + None => write!(f, "{:?}", this.data), + } + } +} + +impl<'tcx, T: DebugWithInfcx>> DebugWithInfcx> for ty::Binder<'tcx, T> { + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_tuple("Binder") + .field(&this.map(|data| data.as_ref().skip_binder())) + .field(&this.data.bound_vars()) + .finish() + } +} + /////////////////////////////////////////////////////////////////////////// // Atomic structs // diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 94746fbdc19..b5f9df9c162 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -35,9 +35,12 @@ use std::ops::{ControlFlow, Deref, Range}; use ty::util::IntTypeExt; use rustc_type_ir::sty::TyKind::*; +use rustc_type_ir::CollectAndApply; +use rustc_type_ir::ConstKind as IrConstKind; +use rustc_type_ir::DebugWithInfcx; +use rustc_type_ir::DynKind; +use rustc_type_ir::RegionKind as IrRegionKind; use rustc_type_ir::TyKind as IrTyKind; -use rustc_type_ir::{CollectAndApply, ConstKind as IrConstKind}; -use rustc_type_ir::{DynKind, RegionKind as IrRegionKind}; use super::GenericParamDefKind; @@ -694,6 +697,15 @@ pub enum ExistentialPredicate<'tcx> { AutoTrait(DefId), } +impl<'tcx> DebugWithInfcx> for ExistentialPredicate<'tcx> { + fn fmt>>( + this: rustc_type_ir::OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + fmt::Debug::fmt(&this.data, f) + } +} + impl<'tcx> ExistentialPredicate<'tcx> { /// Compares via an ordering that will not change if modules are reordered or other changes are /// made to the tree. In particular, this ordering is preserved across incremental compilations. @@ -1574,12 +1586,6 @@ impl<'tcx> Deref for Region<'tcx> { } } -impl<'tcx> fmt::Debug for Region<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:?}", self.kind()) - } -} - #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)] #[derive(HashStable)] pub struct EarlyBoundRegion { diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 4d5f5b8658c..e1a58b97557 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -17,7 +17,6 @@ use smallvec::SmallVec; use core::intrinsics; use std::cmp::Ordering; -use std::fmt; use std::marker::PhantomData; use std::mem; use std::num::NonZeroUsize; @@ -80,16 +79,6 @@ impl<'tcx> GenericArgKind<'tcx> { } } -impl<'tcx> fmt::Debug for GenericArg<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.unpack() { - GenericArgKind::Lifetime(lt) => lt.fmt(f), - GenericArgKind::Type(ty) => ty.fmt(f), - GenericArgKind::Const(ct) => ct.fmt(f), - } - } -} - impl<'tcx> Ord for GenericArg<'tcx> { fn cmp(&self, other: &GenericArg<'tcx>) -> Ordering { self.unpack().cmp(&other.unpack()) diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 878a6b784ed..9ca26d18ae1 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -31,6 +31,7 @@ mod macros; mod structural_impls; pub use codec::*; +pub use structural_impls::{DebugWithInfcx, InferCtxtLike, OptWithInfcx}; pub use sty::*; pub use ty_info::*; @@ -39,41 +40,41 @@ pub trait HashStableContext {} pub trait Interner: Sized { type AdtDef: Clone + Debug + Hash + Ord; - type SubstsRef: Clone + Debug + Hash + Ord; + type SubstsRef: Clone + DebugWithInfcx + Hash + Ord; type DefId: Clone + Debug + Hash + Ord; type Binder; - type Ty: Clone + Debug + Hash + Ord; - type Const: Clone + Debug + Hash + Ord; - type Region: Clone + Debug + Hash + Ord; + type Ty: Clone + DebugWithInfcx + Hash + Ord; + type Const: Clone + DebugWithInfcx + Hash + Ord; + type Region: Clone + DebugWithInfcx + Hash + Ord; type Predicate; type TypeAndMut: Clone + Debug + Hash + Ord; type Mutability: Clone + Debug + Hash + Ord; type Movability: Clone + Debug + Hash + Ord; - type PolyFnSig: Clone + Debug + Hash + Ord; - type ListBinderExistentialPredicate: Clone + Debug + Hash + Ord; - type BinderListTy: Clone + Debug + Hash + Ord; + type PolyFnSig: Clone + DebugWithInfcx + Hash + Ord; + type ListBinderExistentialPredicate: Clone + DebugWithInfcx + Hash + Ord; + type BinderListTy: Clone + DebugWithInfcx + Hash + Ord; type ListTy: Clone + Debug + Hash + Ord + IntoIterator; - type AliasTy: Clone + Debug + Hash + Ord; + type AliasTy: Clone + DebugWithInfcx + Hash + Ord; type ParamTy: Clone + Debug + Hash + Ord; type BoundTy: Clone + Debug + Hash + Ord; type PlaceholderType: Clone + Debug + Hash + Ord; + type InferTy: Clone + DebugWithInfcx + Hash + Ord; type ErrorGuaranteed: Clone + Debug + Hash + Ord; type PredicateKind: Clone + Debug + Hash + PartialEq + Eq; type AllocId: Clone + Debug + Hash + Ord; - type InferConst: Clone + Debug + Hash + Ord; - type AliasConst: Clone + Debug + Hash + Ord; + type InferConst: Clone + DebugWithInfcx + Hash + Ord; + type AliasConst: Clone + DebugWithInfcx + Hash + Ord; type PlaceholderConst: Clone + Debug + Hash + Ord; type ParamConst: Clone + Debug + Hash + Ord; type BoundConst: Clone + Debug + Hash + Ord; - type InferTy: Clone + Debug + Hash + Ord; type ValueConst: Clone + Debug + Hash + Ord; - type ExprConst: Clone + Debug + Hash + Ord; + type ExprConst: Clone + DebugWithInfcx + Hash + Ord; type EarlyBoundRegion: Clone + Debug + Hash + Ord; type BoundRegion: Clone + Debug + Hash + Ord; type FreeRegion: Clone + Debug + Hash + Ord; - type RegionVid: Clone + Debug + Hash + Ord; + type RegionVid: Clone + DebugWithInfcx + Hash + Ord; type PlaceholderRegion: Clone + Debug + Hash + Ord; fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Self::Mutability); @@ -775,20 +776,6 @@ impl fmt::Debug for FloatVid { } } -impl fmt::Debug for InferTy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use InferTy::*; - match *self { - TyVar(ref v) => v.fmt(f), - IntVar(ref v) => v.fmt(f), - FloatVar(ref v) => v.fmt(f), - FreshTy(v) => write!(f, "FreshTy({v:?})"), - FreshIntTy(v) => write!(f, "FreshIntTy({v:?})"), - FreshFloatTy(v) => write!(f, "FreshFloatTy({v:?})"), - } - } -} - impl fmt::Debug for Variance { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(match *self { diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index 1e42175f6e3..1a2d6d64eb0 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -4,12 +4,13 @@ use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; -use crate::{ConstKind, FloatTy, IntTy, Interner, UintTy}; +use crate::{ConstKind, FloatTy, InferTy, IntTy, Interner, UintTy, UniverseIndex}; use rustc_data_structures::functor::IdFunctor; use rustc_data_structures::sync::Lrc; use rustc_index::{Idx, IndexVec}; use core::fmt; +use std::marker::PhantomData; use std::ops::ControlFlow; /////////////////////////////////////////////////////////////////////////// @@ -165,6 +166,116 @@ impl, Ix: Idx> TypeVisitable for IndexVec { + fn universe_of_ty(&self, ty: I::InferTy) -> Option; + fn universe_of_lt(&self, lt: I::RegionVid) -> Option; + fn universe_of_ct(&self, ct: I::InferConst) -> Option; +} + +impl InferCtxtLike for core::convert::Infallible { + fn universe_of_ty(&self, _ty: ::InferTy) -> Option { + match *self {} + } + fn universe_of_ct(&self, _ct: ::InferConst) -> Option { + match *self {} + } + fn universe_of_lt(&self, _lt: ::RegionVid) -> Option { + match *self {} + } +} + +pub trait DebugWithInfcx: fmt::Debug { + fn fmt>( + this: OptWithInfcx<'_, I, InfCtx, &Self>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result; +} + +impl + ?Sized> DebugWithInfcx for &'_ T { + fn fmt>( + this: OptWithInfcx<'_, I, InfCtx, &Self>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + >::fmt(this.map(|&data| data), f) + } +} +impl> DebugWithInfcx for [T] { + fn fmt>( + this: OptWithInfcx<'_, I, InfCtx, &Self>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + match f.alternate() { + true => { + write!(f, "[\n")?; + for element in this.data.iter() { + write!(f, "{:?},\n", &this.wrap(element))?; + } + write!(f, "]") + } + false => { + write!(f, "[")?; + if this.data.len() > 0 { + for element in &this.data[..(this.data.len() - 1)] { + write!(f, "{:?}, ", &this.wrap(element))?; + } + if let Some(element) = this.data.last() { + write!(f, "{:?}", &this.wrap(element))?; + } + } + write!(f, "]") + } + } + } +} + +pub struct OptWithInfcx<'a, I: Interner, InfCtx: InferCtxtLike, T> { + pub data: T, + pub infcx: Option<&'a InfCtx>, + _interner: PhantomData, +} + +impl, T: Copy> Copy for OptWithInfcx<'_, I, InfCtx, T> {} +impl, T: Clone> Clone for OptWithInfcx<'_, I, InfCtx, T> { + fn clone(&self) -> Self { + Self { data: self.data.clone(), infcx: self.infcx, _interner: self._interner } + } +} + +impl<'a, I: Interner, T> OptWithInfcx<'a, I, core::convert::Infallible, T> { + pub fn new_no_ctx(data: T) -> Self { + Self { data, infcx: None, _interner: PhantomData } + } +} + +impl<'a, I: Interner, InfCtx: InferCtxtLike, T> OptWithInfcx<'a, I, InfCtx, T> { + pub fn new(data: T, infcx: &'a InfCtx) -> Self { + Self { data, infcx: Some(infcx), _interner: PhantomData } + } + + pub fn wrap(self, u: U) -> OptWithInfcx<'a, I, InfCtx, U> { + OptWithInfcx { data: u, infcx: self.infcx, _interner: PhantomData } + } + + pub fn map(self, f: impl FnOnce(T) -> U) -> OptWithInfcx<'a, I, InfCtx, U> { + OptWithInfcx { data: f(self.data), infcx: self.infcx, _interner: PhantomData } + } + + pub fn as_ref(&self) -> OptWithInfcx<'a, I, InfCtx, &T> { + OptWithInfcx { data: &self.data, infcx: self.infcx, _interner: PhantomData } + } +} + +impl, T: DebugWithInfcx> fmt::Debug + for OptWithInfcx<'_, I, InfCtx, T> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + DebugWithInfcx::fmt(self.as_ref(), f) + } +} + impl fmt::Debug for IntTy { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.name_str()) @@ -183,20 +294,60 @@ impl fmt::Debug for FloatTy { } } -impl fmt::Debug for ConstKind { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - use ConstKind::*; - match self { - Param(param) => write!(f, "{param:?}"), - Infer(var) => write!(f, "{var:?}"), - Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var.clone()), - Placeholder(placeholder) => write!(f, "{placeholder:?}"), - Unevaluated(uv) => { - write!(f, "{uv:?}") - } - Value(valtree) => write!(f, "{valtree:?}"), - Error(_) => write!(f, "{{const error}}"), - Expr(expr) => write!(f, "{expr:?}"), +impl fmt::Debug for InferTy { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use InferTy::*; + match *self { + TyVar(ref v) => v.fmt(f), + IntVar(ref v) => v.fmt(f), + FloatVar(ref v) => v.fmt(f), + FreshTy(v) => write!(f, "FreshTy({v:?})"), + FreshIntTy(v) => write!(f, "FreshIntTy({v:?})"), + FreshFloatTy(v) => write!(f, "FreshFloatTy({v:?})"), + } + } +} +impl> DebugWithInfcx for InferTy { + fn fmt>( + this: OptWithInfcx<'_, I, InfCtx, &Self>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + use InferTy::*; + match this.infcx.and_then(|infcx| infcx.universe_of_ty(*this.data)) { + None => write!(f, "{:?}", this.data), + Some(universe) => match *this.data { + TyVar(ty_vid) => write!(f, "?{}_{}t", ty_vid.index(), universe.index()), + IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => { + unreachable!() + } + }, + } + } +} + +impl fmt::Debug for ConstKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + OptWithInfcx::new_no_ctx(self).fmt(f) + } +} +impl DebugWithInfcx for ConstKind { + fn fmt>( + this: OptWithInfcx<'_, I, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + use ConstKind::*; + + match this.data { + Param(param) => write!(f, "{param:?}"), + Infer(var) => write!(f, "{:?}", &this.wrap(var)), + Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var.clone()), + Placeholder(placeholder) => write!(f, "{placeholder:?}"), + Unevaluated(uv) => { + write!(f, "{:?}", &this.wrap(uv)) + } + Value(valtree) => write!(f, "{valtree:?}"), + Error(_) => write!(f, "{{const error}}"), + Expr(expr) => write!(f, "{:?}", &this.wrap(expr)), } } } diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index b696f9b9b59..416e8a3d2d2 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -3,7 +3,6 @@ use std::cmp::Ordering; use std::{fmt, hash}; -use crate::DebruijnIndex; use crate::FloatTy; use crate::HashStableContext; use crate::IntTy; @@ -11,6 +10,7 @@ use crate::Interner; use crate::TyDecoder; use crate::TyEncoder; use crate::UintTy; +use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, OptWithInfcx}; use self::RegionKind::*; use self::TyKind::*; @@ -503,42 +503,48 @@ impl hash::Hash for TyKind { } } -// This is manually implemented because a derive would require `I: Debug` -impl fmt::Debug for TyKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { +impl DebugWithInfcx for TyKind { + fn fmt>( + this: OptWithInfcx<'_, I, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> fmt::Result { + match this.data { Bool => write!(f, "bool"), Char => write!(f, "char"), Int(i) => write!(f, "{i:?}"), Uint(u) => write!(f, "{u:?}"), Float(float) => write!(f, "{float:?}"), - Adt(d, s) => f.debug_tuple_field2_finish("Adt", d, s), + Adt(d, s) => f.debug_tuple_field2_finish("Adt", d, &this.wrap(s)), Foreign(d) => f.debug_tuple_field1_finish("Foreign", d), Str => write!(f, "str"), - Array(t, c) => write!(f, "[{t:?}; {c:?}]"), - Slice(t) => write!(f, "[{t:?}]"), + Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)), + Slice(t) => write!(f, "[{:?}]", &this.wrap(t)), RawPtr(p) => { let (ty, mutbl) = I::ty_and_mut_to_parts(p.clone()); match I::mutability_is_mut(mutbl) { true => write!(f, "*mut "), false => write!(f, "*const "), }?; - write!(f, "{ty:?}") + write!(f, "{:?}", &this.wrap(ty)) } Ref(r, t, m) => match I::mutability_is_mut(m.clone()) { - true => write!(f, "&{r:?} mut {t:?}"), - false => write!(f, "&{r:?} {t:?}"), + true => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)), + false => write!(f, "&{:?} {:?}", &this.wrap(r), &this.wrap(t)), }, - FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, s), - FnPtr(s) => write!(f, "{s:?}"), + FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, &this.wrap(s)), + FnPtr(s) => write!(f, "{:?}", &this.wrap(s)), Dynamic(p, r, repr) => match repr { - DynKind::Dyn => write!(f, "dyn {p:?} + {r:?}"), - DynKind::DynStar => write!(f, "dyn* {p:?} + {r:?}"), + DynKind::Dyn => write!(f, "dyn {:?} + {:?}", &this.wrap(p), &this.wrap(r)), + DynKind::DynStar => { + write!(f, "dyn* {:?} + {:?}", &this.wrap(p), &this.wrap(r)) + } }, - Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, s), - Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, s, m), - GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", g), - GeneratorWitnessMIR(d, s) => f.debug_tuple_field2_finish("GeneratorWitnessMIR", d, s), + Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, &this.wrap(s)), + Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, &this.wrap(s), m), + GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", &this.wrap(g)), + GeneratorWitnessMIR(d, s) => { + f.debug_tuple_field2_finish("GeneratorWitnessMIR", d, &this.wrap(s)) + } Never => write!(f, "!"), Tuple(t) => { let mut iter = t.clone().into_iter(); @@ -547,28 +553,34 @@ impl fmt::Debug for TyKind { match iter.next() { None => return write!(f, ")"), - Some(ty) => write!(f, "{ty:?}")?, + Some(ty) => write!(f, "{:?}", &this.wrap(ty))?, }; match iter.next() { None => return write!(f, ",)"), - Some(ty) => write!(f, "{ty:?})")?, + Some(ty) => write!(f, "{:?})", &this.wrap(ty))?, } for ty in iter { - write!(f, ", {ty:?}")?; + write!(f, ", {:?}", &this.wrap(ty))?; } write!(f, ")") } - Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, a), + Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, &this.wrap(a)), Param(p) => write!(f, "{p:?}"), Bound(d, b) => crate::debug_bound_var(f, *d, b), Placeholder(p) => write!(f, "{p:?}"), - Infer(t) => write!(f, "{t:?}"), + Infer(t) => write!(f, "{:?}", this.wrap(t)), TyKind::Error(_) => write!(f, "{{type error}}"), } } } +// This is manually implemented because a derive would require `I: Debug` +impl fmt::Debug for TyKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + OptWithInfcx::new_no_ctx(self).fmt(f) + } +} // This is manually implemented because a derive would require `I: Encodable` impl Encodable for TyKind @@ -1356,21 +1368,23 @@ impl hash::Hash for RegionKind { } } -// This is manually implemented because a derive would require `I: Debug` -impl fmt::Debug for RegionKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { +impl DebugWithInfcx for RegionKind { + fn fmt>( + this: OptWithInfcx<'_, I, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match this.data { ReEarlyBound(data) => write!(f, "ReEarlyBound({data:?})"), ReLateBound(binder_id, bound_region) => { write!(f, "ReLateBound({binder_id:?}, {bound_region:?})") } - ReFree(fr) => fr.fmt(f), + ReFree(fr) => write!(f, "{fr:?}"), ReStatic => f.write_str("ReStatic"), - ReVar(vid) => vid.fmt(f), + ReVar(vid) => write!(f, "{:?}", &this.wrap(vid)), RePlaceholder(placeholder) => write!(f, "RePlaceholder({placeholder:?})"), @@ -1380,6 +1394,11 @@ impl fmt::Debug for RegionKind { } } } +impl fmt::Debug for RegionKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + OptWithInfcx::new_no_ctx(self).fmt(f) + } +} // This is manually implemented because a derive would require `I: Encodable` impl Encodable for RegionKind From 6f53e61887b5e918a69915e8f5a721c1f07b9874 Mon Sep 17 00:00:00 2001 From: yukang Date: Sun, 2 Jul 2023 23:29:37 +0800 Subject: [PATCH 15/50] Add filter with next segment while lookup typo for path --- compiler/rustc_resolve/src/late.rs | 8 +-- .../rustc_resolve/src/late/diagnostics.rs | 62 +++++++++++----- .../extern-prelude-from-opaque-fail-2018.rs | 29 ++++++++ ...xtern-prelude-from-opaque-fail-2018.stderr | 38 ++++++++++ .../extern-prelude-from-opaque-fail.rs | 1 + .../extern-prelude-from-opaque-fail.stderr | 8 +-- .../builtin-prelude-no-accidents.stderr | 4 -- tests/ui/resolve/112590-2.fixed | 34 +++++++++ tests/ui/resolve/112590-2.rs | 26 +++++++ tests/ui/resolve/112590-2.stderr | 71 +++++++++++++++++++ 10 files changed, 252 insertions(+), 29 deletions(-) create mode 100644 tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.rs create mode 100644 tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr create mode 100644 tests/ui/resolve/112590-2.fixed create mode 100644 tests/ui/resolve/112590-2.rs create mode 100644 tests/ui/resolve/112590-2.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index bca95ce54ad..97feb3ddc11 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3503,7 +3503,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let report_errors = |this: &mut Self, res: Option| { if this.should_report_errs() { let (err, candidates) = - this.smart_resolve_report_errors(path, path, path_span, source, res); + this.smart_resolve_report_errors(path, None, path_span, source, res); let def_id = this.parent_scope.module.nearest_parent_mod(); let instead = res.is_some(); @@ -3555,14 +3555,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // Before we start looking for candidates, we have to get our hands // on the type user is trying to perform invocation on; basically: // we're transforming `HashMap::new` into just `HashMap`. - let prefix_path = match path.split_last() { - Some((_, path)) if !path.is_empty() => path, + let (following_seg, prefix_path) = match path.split_last() { + Some((last, path)) if !path.is_empty() => (Some(last), path), _ => return Some(parent_err), }; let (mut err, candidates) = this.smart_resolve_report_errors( prefix_path, - path, + following_seg, path_span, PathSource::Type, None, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 9fec7cc3def..cf1c1787cb5 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -332,15 +332,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { pub(crate) fn smart_resolve_partial_mod_path_errors( &mut self, prefix_path: &[Segment], - path: &[Segment], + following_seg: Option<&Segment>, ) -> Vec { - let next_seg = if path.len() >= prefix_path.len() + 1 && prefix_path.len() == 1 { - path.get(prefix_path.len()) - } else { - None - }; if let Some(segment) = prefix_path.last() && - let Some(next_seg) = next_seg { + let Some(following_seg) = following_seg && + prefix_path.len() == 1 + { let candidates = self.r.lookup_import_candidates( segment.ident, Namespace::TypeNS, @@ -354,7 +351,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { if let Some(def_id) = candidate.did && let Some(module) = self.r.get_module(def_id) { self.r.resolutions(module).borrow().iter().any(|(key, _r)| { - key.ident.name == next_seg.ident.name + key.ident.name == following_seg.ident.name }) } else { false @@ -371,7 +368,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { pub(crate) fn smart_resolve_report_errors( &mut self, path: &[Segment], - full_path: &[Segment], + following_seg: Option<&Segment>, span: Span, source: PathSource<'_>, res: Option, @@ -412,8 +409,15 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { return (err, Vec::new()); } - let (found, candidates) = - self.try_lookup_name_relaxed(&mut err, source, path, full_path, span, res, &base_error); + let (found, candidates) = self.try_lookup_name_relaxed( + &mut err, + source, + path, + following_seg, + span, + res, + &base_error, + ); if found { return (err, candidates); } @@ -422,7 +426,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { // if we have suggested using pattern matching, then don't add needless suggestions // for typos. - fallback |= self.suggest_typo(&mut err, source, path, span, &base_error); + fallback |= self.suggest_typo(&mut err, source, path, following_seg, span, &base_error); if fallback { // Fallback label. @@ -519,7 +523,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err: &mut Diagnostic, source: PathSource<'_>, path: &[Segment], - full_path: &[Segment], + following_seg: Option<&Segment>, span: Span, res: Option, base_error: &BaseError, @@ -590,8 +594,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } // Try finding a suitable replacement. - let typo_sugg = - self.lookup_typo_candidate(path, source.namespace(), is_expected).to_opt_suggestion(); + let typo_sugg = self + .lookup_typo_candidate(path, following_seg, source.namespace(), is_expected) + .to_opt_suggestion(); if path.len() == 1 && self.self_type_is_available() { if let Some(candidate) = self.lookup_assoc_candidate(ident, ns, is_expected, source.is_call()) @@ -690,7 +695,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } if candidates.is_empty() { - candidates = self.smart_resolve_partial_mod_path_errors(path, full_path); + candidates = self.smart_resolve_partial_mod_path_errors(path, following_seg); } return (false, candidates); @@ -776,12 +781,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err: &mut Diagnostic, source: PathSource<'_>, path: &[Segment], + following_seg: Option<&Segment>, span: Span, base_error: &BaseError, ) -> bool { let is_expected = &|res| source.is_expected(res); let ident_span = path.last().map_or(span, |ident| ident.ident.span); - let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected); + let typo_sugg = + self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected); let is_in_same_file = &|sp1, sp2| { let source_map = self.r.tcx.sess.source_map(); let file1 = source_map.span_to_filename(sp1); @@ -1715,6 +1722,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { fn lookup_typo_candidate( &mut self, path: &[Segment], + following_seg: Option<&Segment>, ns: Namespace, filter_fn: &impl Fn(Res) -> bool, ) -> TypoCandidate { @@ -1793,6 +1801,26 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } } + // if next_seg is present, let's filter everything that does not continue the path + if let Some(following_seg) = following_seg { + names.retain(|suggestion| match suggestion.res { + Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _) => { + // FIXME: this is not totally accurate, but mostly works + suggestion.candidate != following_seg.ident.name + } + Res::Def(DefKind::Mod, def_id) => self.r.get_module(def_id).map_or_else( + || false, + |module| { + self.r + .resolutions(module) + .borrow() + .iter() + .any(|(key, _)| key.ident.name == following_seg.ident.name) + }, + ), + _ => true, + }); + } let name = path[path.len() - 1].ident.name; // Make sure error reporting is deterministic. names.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str())); diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.rs b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.rs new file mode 100644 index 00000000000..40c5eacee3b --- /dev/null +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.rs @@ -0,0 +1,29 @@ +// edition:2018 +#![feature(decl_macro)] + +macro a() { + extern crate core as my_core; + mod v { + // Early resolution. + use my_core; //~ ERROR unresolved import `my_core` + } + mod u { + // Late resolution. + fn f() { my_core::mem::drop(0); } + //~^ ERROR failed to resolve: use of undeclared crate or module `my_core` + } +} + +a!(); + +mod v { + // Early resolution. + use my_core; //~ ERROR unresolved import `my_core` +} +mod u { + // Late resolution. + fn f() { my_core::mem::drop(0); } + //~^ ERROR failed to resolve: use of undeclared crate or module `my_core` +} + +fn main() {} diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr new file mode 100644 index 00000000000..0c8945df2f5 --- /dev/null +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr @@ -0,0 +1,38 @@ +error[E0432]: unresolved import `my_core` + --> $DIR/extern-prelude-from-opaque-fail-2018.rs:21:9 + | +LL | use my_core; + | ^^^^^^^ no external crate `my_core` + +error[E0432]: unresolved import `my_core` + --> $DIR/extern-prelude-from-opaque-fail-2018.rs:8:13 + | +LL | use my_core; + | ^^^^^^^ no external crate `my_core` +... +LL | a!(); + | ---- in this macro invocation + | + = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0433]: failed to resolve: use of undeclared crate or module `my_core` + --> $DIR/extern-prelude-from-opaque-fail-2018.rs:12:18 + | +LL | fn f() { my_core::mem::drop(0); } + | ^^^^^^^ use of undeclared crate or module `my_core` +... +LL | a!(); + | ---- in this macro invocation + | + = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0433]: failed to resolve: use of undeclared crate or module `my_core` + --> $DIR/extern-prelude-from-opaque-fail-2018.rs:25:14 + | +LL | fn f() { my_core::mem::drop(0); } + | ^^^^^^^ use of undeclared crate or module `my_core` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0432, E0433. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs b/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs index 571017df4d7..f3fa2dddaef 100644 --- a/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs @@ -1,3 +1,4 @@ +// edition:2015 #![feature(decl_macro)] macro a() { diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr index f1f4caee361..1129fc31f89 100644 --- a/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr @@ -1,11 +1,11 @@ error[E0432]: unresolved import `my_core` - --> $DIR/extern-prelude-from-opaque-fail.rs:20:9 + --> $DIR/extern-prelude-from-opaque-fail.rs:21:9 | LL | use my_core; | ^^^^^^^ no `my_core` in the root error[E0432]: unresolved import `my_core` - --> $DIR/extern-prelude-from-opaque-fail.rs:7:13 + --> $DIR/extern-prelude-from-opaque-fail.rs:8:13 | LL | use my_core; | ^^^^^^^ no `my_core` in the root @@ -16,7 +16,7 @@ LL | a!(); = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: failed to resolve: use of undeclared crate or module `my_core` - --> $DIR/extern-prelude-from-opaque-fail.rs:11:18 + --> $DIR/extern-prelude-from-opaque-fail.rs:12:18 | LL | fn f() { my_core::mem::drop(0); } | ^^^^^^^ use of undeclared crate or module `my_core` @@ -27,7 +27,7 @@ LL | a!(); = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: failed to resolve: use of undeclared crate or module `my_core` - --> $DIR/extern-prelude-from-opaque-fail.rs:24:14 + --> $DIR/extern-prelude-from-opaque-fail.rs:25:14 | LL | fn f() { my_core::mem::drop(0); } | ^^^^^^^ use of undeclared crate or module `my_core` diff --git a/tests/ui/macros/builtin-prelude-no-accidents.stderr b/tests/ui/macros/builtin-prelude-no-accidents.stderr index b726e186241..c1054230bc9 100644 --- a/tests/ui/macros/builtin-prelude-no-accidents.stderr +++ b/tests/ui/macros/builtin-prelude-no-accidents.stderr @@ -26,10 +26,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `vec` LL | type B = vec::Vec; | ^^^ use of undeclared crate or module `vec` | -help: a struct with a similar name exists - | -LL | type B = Vec::Vec; - | ~~~ help: consider importing this module | LL + use std::vec; diff --git a/tests/ui/resolve/112590-2.fixed b/tests/ui/resolve/112590-2.fixed new file mode 100644 index 00000000000..3bfe81ae8d0 --- /dev/null +++ b/tests/ui/resolve/112590-2.fixed @@ -0,0 +1,34 @@ +// run-rustfix +use std::vec; + +use std::sync::atomic::AtomicBool; + +mod foo { + pub mod bar { + pub mod baz { + pub use std::vec::Vec as MyVec; + } + } +} + +mod u { + use foo::bar::baz::MyVec; + +fn _a() { + let _: Vec = MyVec::new(); //~ ERROR failed to resolve + } +} + +mod v { + use foo::bar::baz::MyVec; + +fn _b() { + let _: Vec = MyVec::new(); //~ ERROR failed to resolve + } +} + +fn main() { + let _t: Vec = Vec::new(); //~ ERROR failed to resolve + type _B = vec::Vec::; //~ ERROR failed to resolve + let _t = AtomicBool::new(true); //~ ERROR failed to resolve +} diff --git a/tests/ui/resolve/112590-2.rs b/tests/ui/resolve/112590-2.rs new file mode 100644 index 00000000000..e5914cd676e --- /dev/null +++ b/tests/ui/resolve/112590-2.rs @@ -0,0 +1,26 @@ +// run-rustfix +mod foo { + pub mod bar { + pub mod baz { + pub use std::vec::Vec as MyVec; + } + } +} + +mod u { + fn _a() { + let _: Vec = super::foo::baf::baz::MyVec::new(); //~ ERROR failed to resolve + } +} + +mod v { + fn _b() { + let _: Vec = fox::bar::baz::MyVec::new(); //~ ERROR failed to resolve + } +} + +fn main() { + let _t: Vec = vec::new(); //~ ERROR failed to resolve + type _B = vec::Vec::; //~ ERROR failed to resolve + let _t = std::sync_error::atomic::AtomicBool::new(true); //~ ERROR failed to resolve +} diff --git a/tests/ui/resolve/112590-2.stderr b/tests/ui/resolve/112590-2.stderr new file mode 100644 index 00000000000..0db20249d27 --- /dev/null +++ b/tests/ui/resolve/112590-2.stderr @@ -0,0 +1,71 @@ +error[E0433]: failed to resolve: could not find `baf` in `foo` + --> $DIR/112590-2.rs:12:39 + | +LL | let _: Vec = super::foo::baf::baz::MyVec::new(); + | ^^^ could not find `baf` in `foo` + | +help: consider importing this struct through its public re-export + | +LL + use foo::bar::baz::MyVec; + | +help: if you import `MyVec`, refer to it directly + | +LL - let _: Vec = super::foo::baf::baz::MyVec::new(); +LL + let _: Vec = MyVec::new(); + | + +error[E0433]: failed to resolve: use of undeclared crate or module `fox` + --> $DIR/112590-2.rs:18:27 + | +LL | let _: Vec = fox::bar::baz::MyVec::new(); + | ^^^ use of undeclared crate or module `fox` + | +help: consider importing this struct through its public re-export + | +LL + use foo::bar::baz::MyVec; + | +help: if you import `MyVec`, refer to it directly + | +LL - let _: Vec = fox::bar::baz::MyVec::new(); +LL + let _: Vec = MyVec::new(); + | + +error[E0433]: failed to resolve: use of undeclared crate or module `vec` + --> $DIR/112590-2.rs:24:15 + | +LL | type _B = vec::Vec::; + | ^^^ use of undeclared crate or module `vec` + | +help: consider importing this module + | +LL + use std::vec; + | + +error[E0433]: failed to resolve: could not find `sync_error` in `std` + --> $DIR/112590-2.rs:25:19 + | +LL | let _t = std::sync_error::atomic::AtomicBool::new(true); + | ^^^^^^^^^^ could not find `sync_error` in `std` + | +help: consider importing this struct + | +LL + use std::sync::atomic::AtomicBool; + | +help: if you import `AtomicBool`, refer to it directly + | +LL - let _t = std::sync_error::atomic::AtomicBool::new(true); +LL + let _t = AtomicBool::new(true); + | + +error[E0433]: failed to resolve: use of undeclared crate or module `vec` + --> $DIR/112590-2.rs:23:24 + | +LL | let _t: Vec = vec::new(); + | ^^^ + | | + | use of undeclared crate or module `vec` + | help: a struct with a similar name exists (notice the capitalization): `Vec` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0433`. From 9763472e2b162aeb56b4950a28d829a7e6dd85ee Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 7 Jul 2023 09:49:39 +0800 Subject: [PATCH 16/50] smart_resolve_partial_mod_path_errors should not suggest parent --- compiler/rustc_resolve/src/late/diagnostics.rs | 7 ++++--- tests/ui/resolve/export-fully-qualified-2018.stderr | 5 ----- tests/ui/resolve/export-fully-qualified.stderr | 5 ----- tests/ui/suggestions/crate-or-module-typo.stderr | 5 ----- 4 files changed, 4 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index cf1c1787cb5..73865f81b6d 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -350,9 +350,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { .filter(|candidate| { if let Some(def_id) = candidate.did && let Some(module) = self.r.get_module(def_id) { - self.r.resolutions(module).borrow().iter().any(|(key, _r)| { - key.ident.name == following_seg.ident.name - }) + Some(def_id) != self.parent_scope.module.opt_def_id() && + self.r.resolutions(module).borrow().iter().any(|(key, _r)| { + key.ident.name == following_seg.ident.name + }) } else { false } diff --git a/tests/ui/resolve/export-fully-qualified-2018.stderr b/tests/ui/resolve/export-fully-qualified-2018.stderr index 366ffd9bb2b..b724da930df 100644 --- a/tests/ui/resolve/export-fully-qualified-2018.stderr +++ b/tests/ui/resolve/export-fully-qualified-2018.stderr @@ -3,11 +3,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo` | LL | pub fn bar() { foo::baz(); } | ^^^ use of undeclared crate or module `foo` - | -help: consider importing this module - | -LL + use crate::foo; - | error: aborting due to previous error diff --git a/tests/ui/resolve/export-fully-qualified.stderr b/tests/ui/resolve/export-fully-qualified.stderr index 0cd516ee1b1..a8af0c7c9b8 100644 --- a/tests/ui/resolve/export-fully-qualified.stderr +++ b/tests/ui/resolve/export-fully-qualified.stderr @@ -3,11 +3,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo` | LL | pub fn bar() { foo::baz(); } | ^^^ use of undeclared crate or module `foo` - | -help: consider importing this module - | -LL + use foo; - | error: aborting due to previous error diff --git a/tests/ui/suggestions/crate-or-module-typo.stderr b/tests/ui/suggestions/crate-or-module-typo.stderr index 5e7a7685ab0..98b88b4fb92 100644 --- a/tests/ui/suggestions/crate-or-module-typo.stderr +++ b/tests/ui/suggestions/crate-or-module-typo.stderr @@ -36,11 +36,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `bar` | LL | pub fn bar() { bar::baz(); } | ^^^ use of undeclared crate or module `bar` - | -help: consider importing this module - | -LL + use crate::bar; - | error: aborting due to 4 previous errors From 37b40e592a71ce5c0af7901857f4123f6ff410f3 Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 7 Jul 2023 10:19:30 +0800 Subject: [PATCH 17/50] adjust smart_resolve_partial_mod_path_errors --- compiler/rustc_resolve/src/late/diagnostics.rs | 3 +-- .../feature-gate-extern_absolute_paths.stderr | 9 +++++++++ .../extern-prelude-from-opaque-fail-2018.stderr | 15 +++++++++++++++ .../extern-prelude-from-opaque-fail.stderr | 12 ++++++++++++ tests/ui/suggestions/crate-or-module-typo.stderr | 11 +++++++++++ 5 files changed, 48 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 73865f81b6d..8b65a892b5e 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -335,8 +335,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { following_seg: Option<&Segment>, ) -> Vec { if let Some(segment) = prefix_path.last() && - let Some(following_seg) = following_seg && - prefix_path.len() == 1 + let Some(following_seg) = following_seg { let candidates = self.r.lookup_import_candidates( segment.ident, diff --git a/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr b/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr index 3bae23a4aaa..7de67da9b5d 100644 --- a/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr +++ b/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr @@ -13,6 +13,15 @@ LL | let _: u8 = ::core::default::Default(); | ^^^^ maybe a missing crate `core`? | = help: consider adding `extern crate core` to use the `core` crate +help: consider importing this module + | +LL + use std::default; + | +help: if you import `default`, refer to it directly + | +LL - let _: u8 = ::core::default::Default(); +LL + let _: u8 = default::Default(); + | error: aborting due to 2 previous errors diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr index 0c8945df2f5..7ed15e89caa 100644 --- a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr @@ -24,6 +24,9 @@ LL | fn f() { my_core::mem::drop(0); } LL | a!(); | ---- in this macro invocation | + = help: consider importing one of these items: + std::mem + core::mem = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: failed to resolve: use of undeclared crate or module `my_core` @@ -31,6 +34,18 @@ error[E0433]: failed to resolve: use of undeclared crate or module `my_core` | LL | fn f() { my_core::mem::drop(0); } | ^^^^^^^ use of undeclared crate or module `my_core` + | +help: consider importing one of these items + | +LL + use core::mem; + | +LL + use std::mem; + | +help: if you import `mem`, refer to it directly + | +LL - fn f() { my_core::mem::drop(0); } +LL + fn f() { mem::drop(0); } + | error: aborting due to 4 previous errors diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr index 1129fc31f89..13b2827ef39 100644 --- a/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr @@ -24,6 +24,8 @@ LL | fn f() { my_core::mem::drop(0); } LL | a!(); | ---- in this macro invocation | + = help: consider importing this module: + my_core::mem = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: failed to resolve: use of undeclared crate or module `my_core` @@ -31,6 +33,16 @@ error[E0433]: failed to resolve: use of undeclared crate or module `my_core` | LL | fn f() { my_core::mem::drop(0); } | ^^^^^^^ use of undeclared crate or module `my_core` + | +help: consider importing this module + | +LL + use my_core::mem; + | +help: if you import `mem`, refer to it directly + | +LL - fn f() { my_core::mem::drop(0); } +LL + fn f() { mem::drop(0); } + | error: aborting due to 4 previous errors diff --git a/tests/ui/suggestions/crate-or-module-typo.stderr b/tests/ui/suggestions/crate-or-module-typo.stderr index 98b88b4fb92..9ece31e76f0 100644 --- a/tests/ui/suggestions/crate-or-module-typo.stderr +++ b/tests/ui/suggestions/crate-or-module-typo.stderr @@ -30,6 +30,17 @@ help: there is a crate or module with a similar name | LL | bar: std::cell::Cell | ~~~ +help: consider importing one of these items + | +LL + use core::cell; + | +LL + use std::cell; + | +help: if you import `cell`, refer to it directly + | +LL - bar: st::cell::Cell +LL + bar: cell::Cell + | error[E0433]: failed to resolve: use of undeclared crate or module `bar` --> $DIR/crate-or-module-typo.rs:6:20 From b5208b36114ce3cb17835f22ea23fd3310e281c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Tue, 4 Jul 2023 11:47:06 +0800 Subject: [PATCH 18/50] Don't suggest `impl Trait` in path position --- .../src/infer/error_reporting/need_type_info.rs | 12 ++++++++++-- ...3264-incorrect-impl-trait-in-path-suggestion.rs | 12 ++++++++++++ ...-incorrect-impl-trait-in-path-suggestion.stderr | 14 ++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.rs create mode 100644 tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index bb75ecc6adb..a90a41f5d70 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -162,10 +162,18 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte let mut infcx_inner = infcx.inner.borrow_mut(); let ty_vars = infcx_inner.type_variables(); let var_origin = ty_vars.var_origin(ty_vid); - if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = var_origin.kind + if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) = var_origin.kind && !var_origin.span.from_expansion() { - Some(name) + let generics = infcx.tcx.generics_of(infcx.tcx.parent(def_id)); + let idx = generics.param_def_id_to_index(infcx.tcx, def_id).unwrap(); + let generic_param_def = generics.param_at(idx as usize, infcx.tcx); + if let ty::GenericParamDefKind::Type { synthetic: true, .. } = generic_param_def.kind + { + None + } else { + Some(name) + } } else { None } diff --git a/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.rs b/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.rs new file mode 100644 index 00000000000..5a893f2d8ad --- /dev/null +++ b/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.rs @@ -0,0 +1,12 @@ +trait T {} + +struct S {} + +impl S { + fn owo(&self, _: Option<&impl T>) {} +} + +fn main() { + (S {}).owo(None) + //~^ ERROR type annotations needed +} diff --git a/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr b/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr new file mode 100644 index 00000000000..0ec219415ab --- /dev/null +++ b/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-113264-incorrect-impl-trait-in-path-suggestion.rs:10:16 + | +LL | (S {}).owo(None) + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` + | +help: consider specifying the generic argument + | +LL | (S {}).owo(None::<&_>) + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. From 20429af7a3a9f6d7b4dfbcdc85a4fa8f6187f922 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 24 Jun 2023 00:00:08 -0300 Subject: [PATCH 19/50] Replace RPITIT current impl with new strategy that lowers as a GAT --- compiler/rustc_hir/src/def.rs | 7 +- compiler/rustc_hir/src/target.rs | 11 +- .../rustc_hir_analysis/src/astconv/mod.rs | 4 +- .../rustc_hir_analysis/src/check/check.rs | 18 +- .../src/collect/item_bounds.rs | 8 +- .../rustc_hir_analysis/src/impl_wf_check.rs | 15 +- .../rustc_hir_analysis/src/variance/mod.rs | 10 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 31 +--- compiler/rustc_metadata/src/rmeta/table.rs | 1 - compiler/rustc_middle/src/hir/map/mod.rs | 8 +- compiler/rustc_middle/src/ty/context.rs | 14 +- compiler/rustc_middle/src/ty/mod.rs | 24 +-- compiler/rustc_middle/src/ty/relate.rs | 12 +- compiler/rustc_middle/src/ty/sty.rs | 6 +- .../rustc_monomorphize/src/polymorphize.rs | 1 - compiler/rustc_passes/src/check_attr.rs | 1 - compiler/rustc_privacy/src/lib.rs | 15 +- .../rustc_resolve/src/build_reduced_graph.rs | 1 - compiler/rustc_session/src/options.rs | 3 - .../src/traits/project.rs | 155 +----------------- compiler/rustc_ty_utils/src/assoc.rs | 108 ++++++------ compiler/rustc_ty_utils/src/implied_bounds.rs | 1 - compiler/rustc_ty_utils/src/opaque_types.rs | 1 - compiler/rustc_ty_utils/src/ty.rs | 10 +- src/librustdoc/formats/item_type.rs | 1 - .../passes/collect_intra_doc_links.rs | 4 +- .../bad-inputs-and-output.rs | 2 - .../bad-inputs-and-output.stderr | 48 ++++++ .../return-type-notation/basic.rs | 14 +- .../return-type-notation/equality.rs | 2 - .../return-type-notation/equality.stderr | 17 ++ .../edition-deny-async-fns-2015.rs | 2 - .../edition-deny-async-fns-2015.stderr | 98 +++++++++++ .../in-trait/async-associated-types.rs | 2 - .../in-trait/async-default-fn-overridden.rs | 2 - .../async-example-desugared-boxed-in-trait.rs | 2 - ...nc-example-desugared-boxed-in-trait.stderr | 17 ++ .../in-trait/async-example-desugared-boxed.rs | 2 - .../async-example-desugared-boxed.stderr | 11 ++ .../in-trait/async-example-desugared-extra.rs | 2 - .../async-example-desugared-in-trait.rs | 2 - .../async-example-desugared-manual.rs | 2 - .../async-example-desugared-manual.stderr | 11 ++ .../in-trait/async-example-desugared.rs | 2 - .../in-trait/async-generics-and-bounds.rs | 2 - .../in-trait/async-generics-and-bounds.stderr | 37 +++++ .../ui/async-await/in-trait/async-generics.rs | 2 - .../in-trait/async-generics.stderr | 37 +++++ .../in-trait/async-lifetimes-and-bounds.rs | 2 - .../async-await/in-trait/async-lifetimes.rs | 2 - .../in-trait/async-recursive-generic.rs | 2 - .../in-trait/async-recursive-generic.stderr | 12 ++ .../async-await/in-trait/async-recursive.rs | 2 - .../in-trait/async-recursive.stderr | 12 ++ .../ui/async-await/in-trait/bad-signatures.rs | 2 - .../in-trait/bad-signatures.stderr | 17 ++ ...ont-project-to-specializable-projection.rs | 2 - ...project-to-specializable-projection.stderr | 25 +++ .../ui/async-await/in-trait/early-bound-1.rs | 2 - .../ui/async-await/in-trait/early-bound-2.rs | 2 - .../async-await/in-trait/fn-not-async-err2.rs | 2 - .../in-trait/fn-not-async-err2.stderr | 12 ++ .../ui/async-await/in-trait/implied-bounds.rs | 2 - tests/ui/async-await/in-trait/issue-102138.rs | 2 - tests/ui/async-await/in-trait/issue-102219.rs | 2 - tests/ui/async-await/in-trait/issue-102310.rs | 2 - tests/ui/async-await/in-trait/issue-104678.rs | 2 - .../async-await/in-trait/lifetime-mismatch.rs | 2 - .../in-trait/lifetime-mismatch.stderr | 12 ++ .../in-trait/missing-feature-flag.rs | 2 - .../in-trait/missing-feature-flag.stderr | 30 ++++ .../in-trait/missing-send-bound.rs | 2 - .../in-trait/missing-send-bound.stderr | 20 +++ .../ui/async-await/in-trait/object-safety.rs | 2 - .../async-await/in-trait/object-safety.stderr | 18 ++ .../in-trait/return-not-existing-pair.rs | 2 - .../in-trait/return-not-existing-pair.stderr | 39 +++++ ...eturn-not-existing-type-wrapping-rpitit.rs | 2 - ...n-not-existing-type-wrapping-rpitit.stderr | 9 + .../in-trait/return-type-suggestion.rs | 2 - .../in-trait/return-type-suggestion.stderr | 14 ++ .../issue-110963-early.rs | 2 - .../issue-110963-early.stderr | 37 +++++ .../return-type-notation/issue-110963-late.rs | 2 - .../issue-110963-late.stderr | 11 ++ .../super-method-bound.rs | 2 - .../super-method-bound.stderr | 11 ++ .../return-type-notation/supertrait-bound.rs | 2 - .../supertrait-bound.stderr | 11 ++ .../return-type-notation/ty-or-ct-params.rs | 2 - .../ty-or-ct-params.stderr | 29 ++++ .../feature-gate-return_type_notation.rs | 24 +-- .../impl-trait/in-trait/auxiliary/rpitit.rs | 6 +- .../in-trait/box-coerce-span-in-default.rs | 2 - .../impl-trait/in-trait/deep-match-works.rs | 2 - tests/ui/impl-trait/in-trait/deep-match.rs | 3 - .../ui/impl-trait/in-trait/deep-match.stderr | 15 ++ .../in-trait/default-body-type-err-2.rs | 2 - .../in-trait/default-body-type-err-2.stderr | 11 ++ .../in-trait/default-body-type-err.rs | 3 - .../in-trait/default-body-type-err.stderr | 12 ++ .../in-trait/default-body-with-rpit.rs | 2 - .../in-trait/default-body-with-rpit.stderr | 24 +++ tests/ui/impl-trait/in-trait/default-body.rs | 2 - .../default-method-binder-shifting.rs | 2 - .../in-trait/default-method-constraint.rs | 2 - .../ui/impl-trait/in-trait/doesnt-satisfy.rs | 3 - .../impl-trait/in-trait/doesnt-satisfy.stderr | 17 ++ .../dont-project-to-rpitit-with-no-value.rs | 3 - ...ont-project-to-rpitit-with-no-value.stderr | 12 ++ tests/ui/impl-trait/in-trait/early.rs | 2 - tests/ui/impl-trait/in-trait/encode.rs | 2 - .../in-trait/foreign-dyn-error.stderr | 2 +- tests/ui/impl-trait/in-trait/foreign.rs | 6 +- .../impl-trait/in-trait/generics-mismatch.rs | 3 - .../in-trait/generics-mismatch.stderr | 12 ++ tests/ui/impl-trait/in-trait/issue-102140.rs | 3 - .../impl-trait/in-trait/issue-102140.stderr | 29 ++++ tests/ui/impl-trait/in-trait/issue-102301.rs | 2 - tests/ui/impl-trait/in-trait/issue-102571.rs | 3 - .../impl-trait/in-trait/issue-102571.stderr | 14 ++ tests/ui/impl-trait/in-trait/nested-rpitit.rs | 2 - tests/ui/impl-trait/in-trait/object-safety.rs | 3 - .../impl-trait/in-trait/object-safety.stderr | 49 ++++++ .../in-trait/opaque-in-impl-is-opaque.rs | 3 - .../in-trait/opaque-in-impl-is-opaque.stderr | 17 ++ .../ui/impl-trait/in-trait/opaque-in-impl.rs | 2 - .../in-trait/return-dont-satisfy-bounds.rs | 3 - .../return-dont-satisfy-bounds.stderr | 16 ++ tests/ui/impl-trait/in-trait/reveal.rs | 2 - .../impl-trait/in-trait/signature-mismatch.rs | 2 - .../in-trait/signature-mismatch.stderr | 61 +++++++ .../in-trait/specialization-broken.rs | 3 - .../in-trait/specialization-broken.stderr | 31 ++++ .../in-trait/specialization-substs-remap.rs | 2 - tests/ui/impl-trait/in-trait/success.rs | 2 - .../in-trait/trait-more-generics-than-impl.rs | 3 - .../trait-more-generics-than-impl.stderr | 12 ++ .../impl-trait/in-trait/unconstrained-lt.rs | 7 +- .../in-trait/unconstrained-lt.stderr | 9 + .../impl-trait/in-trait/variances-of-gat.rs | 2 - tests/ui/impl-trait/in-trait/wf-bounds.rs | 2 - tests/ui/impl-trait/in-trait/wf-bounds.stderr | 57 +++++++ tests/ui/impl-trait/in-trait/where-clause.rs | 2 - .../issue-103052-2.rs | 3 - .../issue-103052-2.stderr | 15 ++ 146 files changed, 1106 insertions(+), 586 deletions(-) create mode 100644 tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr create mode 100644 tests/ui/associated-type-bounds/return-type-notation/equality.stderr create mode 100644 tests/ui/async-await/edition-deny-async-fns-2015.stderr create mode 100644 tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr create mode 100644 tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr create mode 100644 tests/ui/async-await/in-trait/async-example-desugared-manual.stderr create mode 100644 tests/ui/async-await/in-trait/async-generics-and-bounds.stderr create mode 100644 tests/ui/async-await/in-trait/async-generics.stderr create mode 100644 tests/ui/async-await/in-trait/async-recursive-generic.stderr create mode 100644 tests/ui/async-await/in-trait/async-recursive.stderr create mode 100644 tests/ui/async-await/in-trait/bad-signatures.stderr create mode 100644 tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr create mode 100644 tests/ui/async-await/in-trait/fn-not-async-err2.stderr create mode 100644 tests/ui/async-await/in-trait/lifetime-mismatch.stderr create mode 100644 tests/ui/async-await/in-trait/missing-feature-flag.stderr create mode 100644 tests/ui/async-await/in-trait/missing-send-bound.stderr create mode 100644 tests/ui/async-await/in-trait/object-safety.stderr create mode 100644 tests/ui/async-await/in-trait/return-not-existing-pair.stderr create mode 100644 tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.stderr create mode 100644 tests/ui/async-await/in-trait/return-type-suggestion.stderr create mode 100644 tests/ui/async-await/return-type-notation/issue-110963-early.stderr create mode 100644 tests/ui/async-await/return-type-notation/issue-110963-late.stderr create mode 100644 tests/ui/async-await/return-type-notation/super-method-bound.stderr create mode 100644 tests/ui/async-await/return-type-notation/supertrait-bound.stderr create mode 100644 tests/ui/async-await/return-type-notation/ty-or-ct-params.stderr create mode 100644 tests/ui/impl-trait/in-trait/deep-match.stderr create mode 100644 tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr create mode 100644 tests/ui/impl-trait/in-trait/default-body-type-err.stderr create mode 100644 tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr create mode 100644 tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr create mode 100644 tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.stderr create mode 100644 tests/ui/impl-trait/in-trait/generics-mismatch.stderr create mode 100644 tests/ui/impl-trait/in-trait/issue-102140.stderr create mode 100644 tests/ui/impl-trait/in-trait/issue-102571.stderr create mode 100644 tests/ui/impl-trait/in-trait/object-safety.stderr create mode 100644 tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr create mode 100644 tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr create mode 100644 tests/ui/impl-trait/in-trait/signature-mismatch.stderr create mode 100644 tests/ui/impl-trait/in-trait/specialization-broken.stderr create mode 100644 tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr create mode 100644 tests/ui/impl-trait/in-trait/unconstrained-lt.stderr create mode 100644 tests/ui/impl-trait/in-trait/wf-bounds.stderr create mode 100644 tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 30bf8c2ad10..3a4eb90f7f9 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -109,8 +109,6 @@ pub enum DefKind { InlineConst, /// Opaque type, aka `impl Trait`. OpaqueTy, - /// A return-position `impl Trait` in a trait definition - ImplTraitPlaceholder, Field, /// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }` LifetimeParam, @@ -143,7 +141,6 @@ impl DefKind { DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct", DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct", DefKind::OpaqueTy => "opaque type", - DefKind::ImplTraitPlaceholder => "opaque type in trait", DefKind::TyAlias => "type alias", DefKind::TraitAlias => "trait alias", DefKind::AssocTy => "associated type", @@ -227,8 +224,7 @@ impl DefKind { | DefKind::Use | DefKind::ForeignMod | DefKind::GlobalAsm - | DefKind::Impl { .. } - | DefKind::ImplTraitPlaceholder => None, + | DefKind::Impl { .. } => None, } } @@ -262,7 +258,6 @@ impl DefKind { | DefKind::Use | DefKind::ForeignMod | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::Impl { .. } | DefKind::Field | DefKind::TyParam diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 961deac544a..0d65ddb5642 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -36,7 +36,6 @@ pub enum Target { GlobalAsm, TyAlias, OpaqueTy, - ImplTraitPlaceholder, Enum, Variant, Struct, @@ -80,13 +79,7 @@ impl Target { ItemKind::ForeignMod { .. } => Target::ForeignMod, ItemKind::GlobalAsm(..) => Target::GlobalAsm, ItemKind::TyAlias(..) => Target::TyAlias, - ItemKind::OpaqueTy(ref opaque) => { - if opaque.in_trait { - Target::ImplTraitPlaceholder - } else { - Target::OpaqueTy - } - } + ItemKind::OpaqueTy(..) => Target::OpaqueTy, ItemKind::Enum(..) => Target::Enum, ItemKind::Struct(..) => Target::Struct, ItemKind::Union(..) => Target::Union, @@ -110,7 +103,6 @@ impl Target { DefKind::GlobalAsm => Target::GlobalAsm, DefKind::TyAlias => Target::TyAlias, DefKind::OpaqueTy => Target::OpaqueTy, - DefKind::ImplTraitPlaceholder => Target::ImplTraitPlaceholder, DefKind::Enum => Target::Enum, DefKind::Struct => Target::Struct, DefKind::Union => Target::Union, @@ -165,7 +157,6 @@ impl Target { Target::GlobalAsm => "global asm", Target::TyAlias => "type alias", Target::OpaqueTy => "opaque type", - Target::ImplTraitPlaceholder => "opaque type in trait", Target::Enum => "enum", Target::Variant => "enum variant", Target::Struct => "struct", diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 3d698462840..db3d41ed247 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2128,7 +2128,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let span = path.span; match path.res { - Res::Def(DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder, did) => { + Res::Def(DefKind::OpaqueTy, did) => { // Check for desugared `impl Trait`. assert!(tcx.is_type_alias_impl_trait(did)); let item_segment = path.segments.split_last().unwrap(); @@ -2439,7 +2439,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // If this is an RPITIT and we are using the new RPITIT lowering scheme, we // generate the def_id of an associated type for the trait and return as // type a projection. - let def_id = if in_trait && tcx.lower_impl_trait_in_trait_to_assoc_ty() { + let def_id = if in_trait { tcx.associated_type_for_impl_trait_in_trait(local_def_id).to_def_id() } else { local_def_id.to_def_id() diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 120545c8e5d..91c33b09082 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -302,16 +302,11 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( if let ItemKind::OpaqueTy(&hir::OpaqueTy { origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), - in_trait, .. }) = item.kind { let substs = InternalSubsts::identity_for_item(tcx, def_id); - let opaque_identity_ty = if in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() { - Ty::new_projection(tcx, def_id.to_def_id(), substs) - } else { - Ty::new_opaque(tcx, def_id.to_def_id(), substs) - }; + let opaque_identity_ty = Ty::new_opaque(tcx, def_id.to_def_id(), substs); let mut visitor = ProhibitOpaqueVisitor { opaque_identity_ty, parent_count: tcx.generics_of(def_id).parent_count as u32, @@ -576,17 +571,6 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) { check_opaque(tcx, id); } } - DefKind::ImplTraitPlaceholder => { - let parent = tcx.impl_trait_in_trait_parent_fn(id.owner_id.to_def_id()); - // Only check the validity of this opaque type if the function has a default body - if let hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)), - .. - }) = tcx.hir().get_by_def_id(parent.expect_local()) - { - check_opaque(tcx, id); - } - } DefKind::TyAlias => { let pty_ty = tcx.type_of(id.owner_id).subst_identity(); let generics = tcx.generics_of(id.owner_id); diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 57f74172ed0..d6f33869a03 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -113,16 +113,12 @@ pub(super) fn explicit_item_bounds( .. }) => associated_type_bounds(tcx, def_id, bounds, *span), hir::Node::Item(hir::Item { - kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }), + kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }), span, .. }) => { let substs = InternalSubsts::identity_for_item(tcx, def_id); - let item_ty = if *in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() { - Ty::new_projection(tcx, def_id.to_def_id(), substs) - } else { - Ty::new_opaque(tcx, def_id.to_def_id(), substs) - }; + let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), substs); opaque_type_bounds(tcx, def_id, bounds, item_ty, *span) } hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[], diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 5526dd4b007..d654b0be620 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -109,20 +109,7 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) vec![] } } - ty::AssocKind::Fn => { - if !tcx.lower_impl_trait_in_trait_to_assoc_ty() - && item.defaultness(tcx).has_value() - && tcx.impl_method_has_trait_impl_trait_tys(item.def_id) - && let Ok(table) = tcx.collect_return_position_impl_trait_in_trait_tys(def_id) - { - table.values().copied().flat_map(|ty| { - cgp::parameters_for(&ty.subst_identity(), true) - }).collect() - } else { - vec![] - } - } - ty::AssocKind::Const => vec![], + ty::AssocKind::Fn | ty::AssocKind::Const => vec![], } }) .collect(); diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 066e7449189..c703cb03515 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -56,7 +56,7 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { let crate_map = tcx.crate_variances(()); return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]); } - DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder => { + DefKind::OpaqueTy => { return variance_of_opaque(tcx, item_def_id); } _ => {} @@ -115,14 +115,6 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc { self.visit_opaque(*def_id, substs) } - // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) check whether this is necessary - // at all for RPITITs. - ty::Alias(_, ty::AliasTy { def_id, substs, .. }) - if self.tcx.is_impl_trait_in_trait(*def_id) - && !self.tcx.lower_impl_trait_in_trait_to_assoc_ty() => - { - self.visit_opaque(*def_id, substs) - } _ => t.super_visit_with(self), } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 541c19c3561..01dd35b0e5b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -824,7 +824,6 @@ fn should_encode_span(def_kind: DefKind) -> bool { | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::Impl { .. } | DefKind::Closure @@ -867,7 +866,6 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::LifetimeParam | DefKind::GlobalAsm | DefKind::Generator => false, @@ -902,7 +900,6 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool { | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm @@ -939,7 +936,6 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::GlobalAsm | DefKind::Impl { .. } | DefKind::Closure @@ -966,7 +962,6 @@ fn should_encode_stability(def_kind: DefKind) -> bool { | DefKind::ForeignMod | DefKind::TyAlias | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::Enum | DefKind::Union | DefKind::Impl { .. } @@ -1033,7 +1028,6 @@ fn should_encode_variances(def_kind: DefKind) -> bool { | DefKind::Enum | DefKind::Variant | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::Fn | DefKind::Ctor(..) | DefKind::AssocFn => true, @@ -1083,7 +1077,6 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::Impl { .. } | DefKind::Field | DefKind::TyParam @@ -1134,19 +1127,6 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> } } - DefKind::ImplTraitPlaceholder => { - let parent_def_id = tcx.impl_trait_in_trait_parent_fn(def_id.to_def_id()); - let assoc_item = tcx.associated_item(parent_def_id); - match assoc_item.container { - // Always encode an RPIT in an impl fn, since it always has a body - ty::AssocItemContainer::ImplContainer => true, - ty::AssocItemContainer::TraitContainer => { - // Encode an RPIT for a trait only if the trait has a default body - assoc_item.defaultness(tcx).has_value() - } - } - } - DefKind::AssocTy => { let assoc_item = tcx.associated_item(def_id); match assoc_item.container { @@ -1192,7 +1172,6 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool { | DefKind::Ctor(..) | DefKind::TyAlias | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::ForeignTy | DefKind::Impl { .. } | DefKind::AssocConst @@ -1235,7 +1214,6 @@ fn should_encode_constness(def_kind: DefKind) -> bool { | DefKind::TyAlias | DefKind::OpaqueTy | DefKind::Impl { of_trait: false } - | DefKind::ImplTraitPlaceholder | DefKind::ForeignTy | DefKind::Generator | DefKind::ConstParam @@ -1268,7 +1246,6 @@ fn should_encode_const(def_kind: DefKind) -> bool { | DefKind::Static(..) | DefKind::TyAlias | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::ForeignTy | DefKind::Impl { .. } | DefKind::AssocFn @@ -1289,11 +1266,8 @@ fn should_encode_const(def_kind: DefKind) -> bool { } } -// We only encode impl trait in trait when using `lower-impl-trait-in-trait-to-assoc-ty` unstable -// option. fn should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { - if tcx.lower_impl_trait_in_trait_to_assoc_ty() - && let Some(assoc_item) = tcx.opt_associated_item(def_id) + if let Some(assoc_item) = tcx.opt_associated_item(def_id) && assoc_item.container == ty::AssocItemContainer::TraitContainer && assoc_item.kind == ty::AssocKind::Fn { @@ -1447,9 +1421,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { .is_type_alias_impl_trait .set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id)); } - if let DefKind::ImplTraitPlaceholder = def_kind { - self.encode_explicit_item_bounds(def_id); - } if tcx.impl_method_has_trait_impl_trait_tys(def_id) && let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id) { diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index f002d7f97b9..a4313d79ab1 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -142,7 +142,6 @@ fixed_size_enum! { ( AnonConst ) ( InlineConst ) ( OpaqueTy ) - ( ImplTraitPlaceholder ) ( Field ) ( LifetimeParam ) ( GlobalAsm ) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 5f2eb890c4e..6bb8e632dbe 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -195,13 +195,7 @@ impl<'hir> Map<'hir> { ItemKind::Fn(..) => DefKind::Fn, ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind), ItemKind::Mod(..) => DefKind::Mod, - ItemKind::OpaqueTy(ref opaque) => { - if opaque.in_trait && !self.tcx.lower_impl_trait_in_trait_to_assoc_ty() { - DefKind::ImplTraitPlaceholder - } else { - DefKind::OpaqueTy - } - } + ItemKind::OpaqueTy(..) => DefKind::OpaqueTy, ItemKind::TyAlias(..) => DefKind::TyAlias, ItemKind::Enum(..) => DefKind::Enum, ItemKind::Struct(..) => DefKind::Struct, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 035e978f64c..6990fbbb634 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1036,7 +1036,9 @@ impl<'tcx> TyCtxt<'tcx> { scope_def_id: LocalDefId, ) -> Vec<&'tcx hir::Ty<'tcx>> { let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id); - let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) else { + let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = + self.hir().fn_decl_by_hir_id(hir_id) + else { return vec![]; }; @@ -2002,16 +2004,8 @@ impl<'tcx> TyCtxt<'tcx> { ) } - pub fn lower_impl_trait_in_trait_to_assoc_ty(self) -> bool { - self.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty - } - pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { - if self.lower_impl_trait_in_trait_to_assoc_ty() { - self.opt_rpitit_info(def_id).is_some() - } else { - self.def_kind(def_id) == DefKind::ImplTraitPlaceholder - } + self.opt_rpitit_info(def_id).is_some() } /// Named module children from all kinds of items, including imports. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index aa8bfd3178c..792ee8ebb25 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2688,7 +2688,6 @@ impl<'tcx> TyCtxt<'tcx> { | Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) => fn_def_id, None => { while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn { - debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder); def_id = self.parent(def_id); } def_id @@ -2720,26 +2719,9 @@ impl<'tcx> TyCtxt<'tcx> { let Some(trait_item_def_id) = item.trait_item_def_id else { return false; }; - if self.lower_impl_trait_in_trait_to_assoc_ty() { - return !self - .associated_types_for_impl_traits_in_associated_fn(trait_item_def_id) - .is_empty(); - } - - // FIXME(RPITIT): This does a somewhat manual walk through the signature - // of the trait fn to look for any RPITITs, but that's kinda doing a lot - // of work. We can probably remove this when we refactor RPITITs to be - // associated types. - self.fn_sig(trait_item_def_id).subst_identity().skip_binder().output().walk().any(|arg| { - if let ty::GenericArgKind::Type(ty) = arg.unpack() - && let ty::Alias(ty::Projection, data) = ty.kind() - && self.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder - { - true - } else { - false - } - }) + return !self + .associated_types_for_impl_traits_in_associated_fn(trait_item_def_id) + .is_empty(); } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 5741832c980..54dedf31d9f 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -567,15 +567,9 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( // Alias tend to mostly already be handled downstream due to normalization. (&ty::Alias(a_kind, a_data), &ty::Alias(b_kind, b_data)) => { - // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): This if can be removed - // and the assert uncommented once the new desugaring is stable. - if a_kind == b_kind { - let alias_ty = relation.relate(a_data, b_data)?; - // assert_eq!(a_kind, b_kind); - Ok(Ty::new_alias(tcx, a_kind, alias_ty)) - } else { - Err(TypeError::Sorts(expected_found(relation, a, b))) - } + let alias_ty = relation.relate(a_data, b_data)?; + assert_eq!(a_kind, b_kind); + Ok(Ty::new_alias(tcx, a_kind, alias_ty)) } _ => Err(TypeError::Sorts(expected_found(relation, a, b))), diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 94746fbdc19..2c4ff575755 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1237,7 +1237,7 @@ impl<'tcx> AliasTy<'tcx> { pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind { match tcx.def_kind(self.def_id) { DefKind::AssocTy if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) => ty::Inherent, - DefKind::AssocTy | DefKind::ImplTraitPlaceholder => ty::Projection, + DefKind::AssocTy => ty::Projection, DefKind::OpaqueTy => ty::Opaque, DefKind::TyAlias => ty::Weak, kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), @@ -1265,9 +1265,6 @@ impl<'tcx> AliasTy<'tcx> { pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { match tcx.def_kind(self.def_id) { DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id), - DefKind::ImplTraitPlaceholder => { - tcx.parent(tcx.impl_trait_in_trait_parent_fn(self.def_id)) - } kind => bug!("expected a projection AliasTy; found {kind:?}"), } } @@ -1970,7 +1967,6 @@ impl<'tcx> Ty<'tcx> { (kind, tcx.def_kind(alias_ty.def_id)), (ty::Opaque, DefKind::OpaqueTy) | (ty::Projection | ty::Inherent, DefKind::AssocTy) - | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder) | (ty::Weak, DefKind::TyAlias) ); Ty::new(tcx, Alias(kind, alias_ty)) diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index 88a3e028527..aa2ce65e4cc 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -163,7 +163,6 @@ fn mark_used_by_default_parameters<'tcx>( | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 073760f394e..f48900c3c52 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -694,7 +694,6 @@ impl CheckAttrVisitor<'_> { | Target::GlobalAsm | Target::TyAlias | Target::OpaqueTy - | Target::ImplTraitPlaceholder | Target::Enum | Target::Variant | Target::Struct diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 4fcee9396ed..fe23506b878 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -136,19 +136,7 @@ where fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow { let tcx = self.def_id_visitor.tcx(); - let (trait_ref, assoc_substs) = if tcx.def_kind(projection.def_id) - != DefKind::ImplTraitPlaceholder - { - projection.trait_ref_and_own_substs(tcx) - } else { - // HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys - let def_id = tcx.impl_trait_in_trait_parent_fn(projection.def_id); - let trait_generics = tcx.generics_of(def_id); - ( - ty::TraitRef::new(tcx, def_id, projection.substs.truncate_to(tcx, trait_generics)), - &projection.substs[trait_generics.count()..], - ) - }; + let (trait_ref, assoc_substs) = projection.trait_ref_and_own_substs(tcx); self.visit_trait(trait_ref)?; if V::SHALLOW { ControlFlow::Continue(()) @@ -651,7 +639,6 @@ impl<'tcx> EmbargoVisitor<'tcx> { | DefKind::ForeignTy | DefKind::Fn | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::AssocFn | DefKind::Trait | DefKind::TyParam diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index e6ceedddfa1..ff63e4e33cb 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -949,7 +949,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { | DefKind::TyAlias | DefKind::ForeignTy | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::TraitAlias | DefKind::AssocTy, _, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 7840a0ecf0b..87d67c099ce 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1583,9 +1583,6 @@ options! { "what location details should be tracked when using caller_location, either \ `none`, or a comma separated list of location details, for which \ valid options are `file`, `line`, and `column` (default: `file,line,column`)"), - lower_impl_trait_in_trait_to_assoc_ty: bool = (false, parse_bool, [TRACKED], - "modify the lowering strategy for `impl Trait` in traits so that they are lowered to \ - generic associated types"), ls: bool = (false, parse_bool, [UNTRACKED], "list the symbols defined by a library crate (default: no)"), macro_backtrace: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index a10bca31ff1..4ccfb54ff7c 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -131,8 +131,6 @@ enum ProjectionCandidate<'tcx> { /// From an "impl" (or a "pseudo-impl" returned by select) Select(Selection<'tcx>), - - ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>), } enum ProjectionCandidateSet<'tcx> { @@ -1472,8 +1470,6 @@ fn project<'cx, 'tcx>( let mut candidates = ProjectionCandidateSet::None; - assemble_candidate_for_impl_trait_in_trait(selcx, obligation, &mut candidates); - // Make sure that the following procedures are kept in order. ParamEnv // needs to be first because it has highest priority, and Select checks // the return value of push_candidate which assumes it's ran at last. @@ -1499,7 +1495,7 @@ fn project<'cx, 'tcx>( ProjectionCandidateSet::None => { let tcx = selcx.tcx(); let term = match tcx.def_kind(obligation.predicate.def_id) { - DefKind::AssocTy | DefKind::ImplTraitPlaceholder => Ty::new_projection( + DefKind::AssocTy => Ty::new_projection( tcx, obligation.predicate.def_id, obligation.predicate.substs, @@ -1530,47 +1526,6 @@ fn project<'cx, 'tcx>( } } -/// If the predicate's item is an `ImplTraitPlaceholder`, we do a select on the -/// corresponding trait ref. If this yields an `impl`, then we're able to project -/// to a concrete type, since we have an `impl`'s method to provide the RPITIT. -fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - candidate_set: &mut ProjectionCandidateSet<'tcx>, -) { - let tcx = selcx.tcx(); - if tcx.def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder { - let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id); - - let trait_def_id = tcx.parent(trait_fn_def_id); - let trait_substs = - obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id)); - let trait_predicate = ty::TraitRef::new(tcx, trait_def_id, trait_substs); - - let _ = selcx.infcx.commit_if_ok(|_| { - match selcx.select(&obligation.with(tcx, trait_predicate)) { - Ok(Some(super::ImplSource::UserDefined(data))) => { - candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data)); - Ok(()) - } - Ok(None) => { - candidate_set.mark_ambiguous(); - Err(()) - } - Ok(Some(_)) => { - // Don't know enough about the impl to provide a useful signature - Err(()) - } - Err(e) => { - debug!(error = ?e, "selection error"); - candidate_set.mark_error(e); - Err(()) - } - } - }); - } -} - /// The first thing we have to do is scan through the parameter /// environment to see whether there are any projection predicates /// there that can answer this question. @@ -1739,11 +1694,6 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, ) { - // Can't assemble candidate from impl for RPITIT - if selcx.tcx().def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder { - return; - } - // If we are resolving `>::Item == Type`, // start out by selecting the predicate `T as TraitRef<...>`: let trait_ref = obligation.predicate.trait_ref(selcx.tcx()); @@ -2012,9 +1962,6 @@ fn confirm_candidate<'cx, 'tcx>( ProjectionCandidate::Select(impl_source) => { confirm_select_candidate(selcx, obligation, impl_source) } - ProjectionCandidate::ImplTraitInTrait(data) => { - confirm_impl_trait_in_trait_candidate(selcx, obligation, data) - } }; // When checking for cycle during evaluation, we compare predicates with @@ -2240,8 +2187,7 @@ fn confirm_closure_candidate<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, nested: Vec>, ) -> Progress<'tcx> { - let ty::Closure(_, substs) = - selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind() + let ty::Closure(_, substs) = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind() else { unreachable!() }; @@ -2419,103 +2365,6 @@ fn confirm_impl_candidate<'cx, 'tcx>( } } -fn confirm_impl_trait_in_trait_candidate<'tcx>( - selcx: &mut SelectionContext<'_, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - data: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>, -) -> Progress<'tcx> { - let tcx = selcx.tcx(); - let mut obligations = data.nested; - - let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id); - let leaf_def = match specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) { - Ok(assoc_ty) => assoc_ty, - Err(guar) => return Progress::error(tcx, guar), - }; - // We don't support specialization for RPITITs anyways... yet. - // Also don't try to project to an RPITIT that has no value - if !leaf_def.is_final() || !leaf_def.item.defaultness(tcx).has_value() { - return Progress { term: Ty::new_misc_error(tcx).into(), obligations }; - } - - // Use the default `impl Trait` for the trait, e.g., for a default trait body - if leaf_def.item.container == ty::AssocItemContainer::TraitContainer { - return Progress { - term: Ty::new_opaque(tcx, obligation.predicate.def_id, obligation.predicate.substs) - .into(), - obligations, - }; - } - - // Rebase from {trait}::{fn}::{opaque} to {impl}::{fn}::{opaque}, - // since `data.substs` are the impl substs. - let impl_fn_substs = - obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs); - let impl_fn_substs = translate_substs( - selcx.infcx, - obligation.param_env, - data.impl_def_id, - impl_fn_substs, - leaf_def.defining_node, - ); - - if !check_substs_compatible(tcx, leaf_def.item, impl_fn_substs) { - let err = Ty::new_error_with_message( - tcx, - obligation.cause.span, - "impl method and trait method have different parameters", - ); - return Progress { term: err.into(), obligations }; - } - - let impl_fn_def_id = leaf_def.item.def_id; - - let cause = ObligationCause::new( - obligation.cause.span, - obligation.cause.body_id, - super::ItemObligation(impl_fn_def_id), - ); - let predicates = normalize_with_depth_to( - selcx, - obligation.param_env, - cause.clone(), - obligation.recursion_depth + 1, - tcx.predicates_of(impl_fn_def_id).instantiate(tcx, impl_fn_substs), - &mut obligations, - ); - obligations.extend(predicates.into_iter().map(|(pred, span)| { - Obligation::with_depth( - tcx, - ObligationCause::new( - obligation.cause.span, - obligation.cause.body_id, - if span.is_dummy() { - super::ItemObligation(impl_fn_def_id) - } else { - super::BindingObligation(impl_fn_def_id, span) - }, - ), - obligation.recursion_depth + 1, - obligation.param_env, - pred, - ) - })); - - let ty = normalize_with_depth_to( - selcx, - obligation.param_env, - cause.clone(), - obligation.recursion_depth + 1, - tcx.collect_return_position_impl_trait_in_trait_tys(impl_fn_def_id).map_or_else( - |guar| Ty::new_error(tcx, guar), - |tys| tys[&obligation.predicate.def_id].subst(tcx, impl_fn_substs), - ), - &mut obligations, - ); - - Progress { term: ty.into(), obligations } -} - // Get obligations corresponding to the predicates from the where-clause of the // associated type itself. fn assoc_ty_own_obligations<'cx, 'tcx>( diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 897e7aad48b..7e22ef89ed3 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -24,70 +24,54 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] { let item = tcx.hir().expect_item(def_id); match item.kind { hir::ItemKind::Trait(.., ref trait_item_refs) => { - if tcx.lower_impl_trait_in_trait_to_assoc_ty() { - // We collect RPITITs for each trait method's return type and create a - // corresponding associated item using associated_types_for_impl_traits_in_associated_fn - // query. - tcx.arena.alloc_from_iter( - trait_item_refs - .iter() - .map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()) - .chain( - trait_item_refs - .iter() - .filter(|trait_item_ref| { - matches!(trait_item_ref.kind, hir::AssocItemKind::Fn { .. }) - }) - .flat_map(|trait_item_ref| { - let trait_fn_def_id = - trait_item_ref.id.owner_id.def_id.to_def_id(); - tcx.associated_types_for_impl_traits_in_associated_fn( - trait_fn_def_id, - ) - }) - .map(|def_id| *def_id), - ), - ) - } else { - tcx.arena.alloc_from_iter( - trait_item_refs - .iter() - .map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()), - ) - } + // We collect RPITITs for each trait method's return type and create a + // corresponding associated item using associated_types_for_impl_traits_in_associated_fn + // query. + tcx.arena.alloc_from_iter( + trait_item_refs + .iter() + .map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()) + .chain( + trait_item_refs + .iter() + .filter(|trait_item_ref| { + matches!(trait_item_ref.kind, hir::AssocItemKind::Fn { .. }) + }) + .flat_map(|trait_item_ref| { + let trait_fn_def_id = trait_item_ref.id.owner_id.def_id.to_def_id(); + tcx.associated_types_for_impl_traits_in_associated_fn( + trait_fn_def_id, + ) + }) + .map(|def_id| *def_id), + ), + ) } hir::ItemKind::Impl(ref impl_) => { - if tcx.lower_impl_trait_in_trait_to_assoc_ty() { - // We collect RPITITs for each trait method's return type, on the impl side too and - // create a corresponding associated item using - // associated_types_for_impl_traits_in_associated_fn query. - tcx.arena.alloc_from_iter( - impl_ - .items - .iter() - .map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()) - .chain(impl_.of_trait.iter().flat_map(|_| { - impl_ - .items - .iter() - .filter(|impl_item_ref| { - matches!(impl_item_ref.kind, hir::AssocItemKind::Fn { .. }) - }) - .flat_map(|impl_item_ref| { - let impl_fn_def_id = - impl_item_ref.id.owner_id.def_id.to_def_id(); - tcx.associated_types_for_impl_traits_in_associated_fn( - impl_fn_def_id, - ) - }) - .map(|def_id| *def_id) - })), - ) - } else { - tcx.arena.alloc_from_iter( - impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()), - ) - } + // We collect RPITITs for each trait method's return type, on the impl side too and + // create a corresponding associated item using + // associated_types_for_impl_traits_in_associated_fn query. + tcx.arena.alloc_from_iter( + impl_ + .items + .iter() + .map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()) + .chain(impl_.of_trait.iter().flat_map(|_| { + impl_ + .items + .iter() + .filter(|impl_item_ref| { + matches!(impl_item_ref.kind, hir::AssocItemKind::Fn { .. }) + }) + .flat_map(|impl_item_ref| { + let impl_fn_def_id = impl_item_ref.id.owner_id.def_id.to_def_id(); + tcx.associated_types_for_impl_traits_in_associated_fn( + impl_fn_def_id, + ) + }) + .map(|def_id| *def_id) + })), + ) } _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"), } diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 10dec9a7a32..2822595a8a7 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -75,7 +75,6 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' | DefKind::ForeignMod | DefKind::AnonConst | DefKind::InlineConst - | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 570c3b245cd..87dfacc4c2d 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -318,7 +318,6 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [ | DefKind::ExternCrate | DefKind::Use | DefKind::ForeignMod - | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 6e5c50492c6..43e3c99fb57 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -282,11 +282,7 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { // If we're lowering to associated item, install the opaque type which is just // the `type_of` of the trait's associated item. If we're using the old lowering // strategy, then just reinterpret the associated type like an opaque :^) - let default_ty = if self.tcx.lower_impl_trait_in_trait_to_assoc_ty() { - self.tcx.type_of(shifted_alias_ty.def_id).subst(self.tcx, shifted_alias_ty.substs) - } else { - Ty::new_alias(self.tcx,ty::Opaque, shifted_alias_ty) - }; + let default_ty = self.tcx.type_of(shifted_alias_ty.def_id).subst(self.tcx, shifted_alias_ty.substs); self.predicates.push( ty::Binder::bind_with_vars( @@ -408,9 +404,7 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet for ItemType { | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 0dd9e590b9b..ca511d956b9 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1860,8 +1860,8 @@ fn resolution_failure( } return; } - Trait | TyAlias | ForeignTy | OpaqueTy | ImplTraitPlaceholder - | TraitAlias | TyParam | Static(_) => "associated item", + Trait | TyAlias | ForeignTy | OpaqueTy | TraitAlias | TyParam + | Static(_) => "associated item", Impl { .. } | GlobalAsm => unreachable!("not a path"), } } else { diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs index 771acb6c4e7..58ce41d1a89 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs @@ -1,6 +1,4 @@ // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_type_notation, async_fn_in_trait)] //~^ WARN the feature `return_type_notation` is incomplete diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr new file mode 100644 index 00000000000..95ef7d82fca --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr @@ -0,0 +1,48 @@ +error: return type notation uses `()` instead of `(..)` for elided arguments + --> $DIR/bad-inputs-and-output.rs:18:24 + | +LL | fn baz>() {} + | ^^ help: remove the `..` + +error[E0658]: associated type bounds are unstable + --> $DIR/bad-inputs-and-output.rs:10:17 + | +LL | fn foo>() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/bad-inputs-and-output.rs:14:17 + | +LL | fn bar (): Send>>() {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/bad-inputs-and-output.rs:3:12 + | +LL | #![feature(return_type_notation, async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: argument types not allowed with return type notation + --> $DIR/bad-inputs-and-output.rs:10:23 + | +LL | fn foo>() {} + | ^^^^^ help: remove the input types: `()` + +error: return type not allowed with return type notation + --> $DIR/bad-inputs-and-output.rs:14:25 + | +LL | fn bar (): Send>>() {} + | ^^^^^^ help: remove the return type + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.rs b/tests/ui/associated-type-bounds/return-type-notation/basic.rs index d443c9dc11b..3dd9249a791 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/basic.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/basic.rs @@ -1,9 +1,6 @@ -// revisions: current_with current_without next_with next_without -// [next_with] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// [next_without] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: with without // edition: 2021 -// [current_with] check-pass -// [next_with] check-pass +// [with] check-pass #![feature(return_type_notation, async_fn_in_trait)] //~^ WARN the feature `return_type_notation` is incomplete @@ -20,12 +17,11 @@ async fn foo() -> Result<(), ()> { fn is_send(_: impl Send) {} fn test< - #[cfg(any(current_with, next_with))] T: Foo, - #[cfg(any(current_without, next_without))] T: Foo, + #[cfg(with)] T: Foo, + #[cfg(without)] T: Foo, >() { is_send(foo::()); - //[current_without]~^ ERROR future cannot be sent between threads safely - //[next_without]~^^ ERROR future cannot be sent between threads safely + //[without]~^ ERROR future cannot be sent between threads safely } fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.rs b/tests/ui/associated-type-bounds/return-type-notation/equality.rs index 0d6545cc298..6884305d7b3 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/equality.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/equality.rs @@ -1,6 +1,4 @@ // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_type_notation, async_fn_in_trait)] //~^ WARN the feature `return_type_notation` is incomplete diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.stderr b/tests/ui/associated-type-bounds/return-type-notation/equality.stderr new file mode 100644 index 00000000000..490bfdc4c3c --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/equality.stderr @@ -0,0 +1,17 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/equality.rs:3:12 + | +LL | #![feature(return_type_notation, async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: return type notation is not allowed to use type equality + --> $DIR/equality.rs:12:18 + | +LL | fn test>>>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/async-await/edition-deny-async-fns-2015.rs b/tests/ui/async-await/edition-deny-async-fns-2015.rs index d4c30dc9d82..6bd6d879a4a 100644 --- a/tests/ui/async-await/edition-deny-async-fns-2015.rs +++ b/tests/ui/async-await/edition-deny-async-fns-2015.rs @@ -1,6 +1,4 @@ // edition:2015 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015 diff --git a/tests/ui/async-await/edition-deny-async-fns-2015.stderr b/tests/ui/async-await/edition-deny-async-fns-2015.stderr new file mode 100644 index 00000000000..ba918eb28de --- /dev/null +++ b/tests/ui/async-await/edition-deny-async-fns-2015.stderr @@ -0,0 +1,98 @@ +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:3:1 + | +LL | async fn foo() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:5:12 + | +LL | fn baz() { async fn foo() {} } + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:7:1 + | +LL | async fn async_baz() { + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:8:5 + | +LL | async fn bar() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:14:5 + | +LL | async fn foo() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:18:5 + | +LL | async fn foo() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:36:9 + | +LL | async fn bar() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:26:9 + | +LL | async fn foo() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:31:13 + | +LL | async fn bar() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/edition-deny-async-fns-2015.rs:18:5 + | +LL | async fn foo() {} + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0670, E0706. +For more information about an error, try `rustc --explain E0670`. diff --git a/tests/ui/async-await/in-trait/async-associated-types.rs b/tests/ui/async-await/in-trait/async-associated-types.rs index 89ca4039bce..974f5aaff83 100644 --- a/tests/ui/async-await/in-trait/async-associated-types.rs +++ b/tests/ui/async-await/in-trait/async-associated-types.rs @@ -1,7 +1,5 @@ // check-pass // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![feature(impl_trait_projections)] diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs index 99c3ba6a3c2..06413fe6f82 100644 --- a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs +++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs @@ -1,7 +1,5 @@ // run-pass // edition:2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs index 7b53379b24b..38ba297189c 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs @@ -1,6 +1,4 @@ // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![feature(return_position_impl_trait_in_trait)] diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr new file mode 100644 index 00000000000..168ef8e9ee4 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr @@ -0,0 +1,17 @@ +error[E0053]: method `foo` has an incompatible type for trait + --> $DIR/async-example-desugared-boxed-in-trait.rs:15:28 + | +LL | async fn foo(&self) -> i32 { + | ^^^ expected `Pin>>`, found future + | +note: type in trait + --> $DIR/async-example-desugared-boxed-in-trait.rs:11:22 + | +LL | fn foo(&self) -> Pin + '_>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected signature `fn(&i32) -> Pin>>` + found signature `fn(&i32) -> impl Future` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs index 916488ffafa..1b1b3cffd58 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs @@ -1,6 +1,4 @@ // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![feature(return_position_impl_trait_in_trait)] diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr new file mode 100644 index 00000000000..60fa534a64f --- /dev/null +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr @@ -0,0 +1,11 @@ +error: method `foo` should be async because the method from the trait is async + --> $DIR/async-example-desugared-boxed.rs:15:5 + | +LL | async fn foo(&self) -> i32; + | --------------------------- required because the trait method is async +... +LL | fn foo(&self) -> Pin + '_>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs index edac0b374a3..81e1e59a362 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs @@ -1,7 +1,5 @@ // check-pass // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![feature(return_position_impl_trait_in_trait)] diff --git a/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs b/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs index 934f7643dd1..feeda719e03 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs @@ -1,7 +1,5 @@ // check-pass // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![feature(return_position_impl_trait_in_trait)] diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs index 4883828d32f..71473e7455f 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs @@ -1,6 +1,4 @@ // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![feature(return_position_impl_trait_in_trait)] diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr new file mode 100644 index 00000000000..567a36a86d1 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr @@ -0,0 +1,11 @@ +error: method `foo` should be async because the method from the trait is async + --> $DIR/async-example-desugared-manual.rs:23:5 + | +LL | async fn foo(&self) -> i32; + | --------------------------- required because the trait method is async +... +LL | fn foo(&self) -> MyFuture { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/async-await/in-trait/async-example-desugared.rs b/tests/ui/async-await/in-trait/async-example-desugared.rs index 214171b2e2c..fb92ec78674 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared.rs @@ -1,7 +1,5 @@ // check-pass // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![feature(return_position_impl_trait_in_trait)] diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.rs b/tests/ui/async-await/in-trait/async-generics-and-bounds.rs index 146e74ec2d0..a73d55adfec 100644 --- a/tests/ui/async-await/in-trait/async-generics-and-bounds.rs +++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.rs @@ -1,8 +1,6 @@ // check-fail // known-bug: #102682 // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr new file mode 100644 index 00000000000..f1f0d7e5907 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr @@ -0,0 +1,37 @@ +error[E0311]: the parameter type `U` may not live long enough + --> $DIR/async-generics-and-bounds.rs:12:28 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^^^^^^^ + | +note: the parameter type `U` must be valid for the anonymous lifetime defined here... + --> $DIR/async-generics-and-bounds.rs:12:18 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^^^^^ +note: ...so that the reference type `&(T, U)` does not outlive the data it points at + --> $DIR/async-generics-and-bounds.rs:12:28 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^^^^^^^ + +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/async-generics-and-bounds.rs:12:28 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^^^^^^^ + | +note: the parameter type `T` must be valid for the anonymous lifetime defined here... + --> $DIR/async-generics-and-bounds.rs:12:18 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^^^^^ +note: ...so that the reference type `&(T, U)` does not outlive the data it points at + --> $DIR/async-generics-and-bounds.rs:12:28 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0311`. diff --git a/tests/ui/async-await/in-trait/async-generics.rs b/tests/ui/async-await/in-trait/async-generics.rs index 507500abf4e..67000e5770e 100644 --- a/tests/ui/async-await/in-trait/async-generics.rs +++ b/tests/ui/async-await/in-trait/async-generics.rs @@ -1,8 +1,6 @@ // check-fail // known-bug: #102682 // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/async-await/in-trait/async-generics.stderr b/tests/ui/async-await/in-trait/async-generics.stderr new file mode 100644 index 00000000000..2f05564564c --- /dev/null +++ b/tests/ui/async-await/in-trait/async-generics.stderr @@ -0,0 +1,37 @@ +error[E0311]: the parameter type `U` may not live long enough + --> $DIR/async-generics.rs:9:28 + | +LL | async fn foo(&self) -> &(T, U); + | ^^^^^^^ + | +note: the parameter type `U` must be valid for the anonymous lifetime defined here... + --> $DIR/async-generics.rs:9:18 + | +LL | async fn foo(&self) -> &(T, U); + | ^^^^^ +note: ...so that the reference type `&(T, U)` does not outlive the data it points at + --> $DIR/async-generics.rs:9:28 + | +LL | async fn foo(&self) -> &(T, U); + | ^^^^^^^ + +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/async-generics.rs:9:28 + | +LL | async fn foo(&self) -> &(T, U); + | ^^^^^^^ + | +note: the parameter type `T` must be valid for the anonymous lifetime defined here... + --> $DIR/async-generics.rs:9:18 + | +LL | async fn foo(&self) -> &(T, U); + | ^^^^^ +note: ...so that the reference type `&(T, U)` does not outlive the data it points at + --> $DIR/async-generics.rs:9:28 + | +LL | async fn foo(&self) -> &(T, U); + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0311`. diff --git a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs index 9869a8d71c2..d5481d277e4 100644 --- a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs +++ b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs @@ -1,7 +1,5 @@ // check-pass // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/async-await/in-trait/async-lifetimes.rs b/tests/ui/async-await/in-trait/async-lifetimes.rs index ecbd1910ac4..f298e45d239 100644 --- a/tests/ui/async-await/in-trait/async-lifetimes.rs +++ b/tests/ui/async-await/in-trait/async-lifetimes.rs @@ -1,7 +1,5 @@ // check-pass // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.rs b/tests/ui/async-await/in-trait/async-recursive-generic.rs index 64c6ba15c0c..6839abd381c 100644 --- a/tests/ui/async-await/in-trait/async-recursive-generic.rs +++ b/tests/ui/async-await/in-trait/async-recursive-generic.rs @@ -1,6 +1,4 @@ // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.stderr b/tests/ui/async-await/in-trait/async-recursive-generic.stderr new file mode 100644 index 00000000000..cab173bdd5b --- /dev/null +++ b/tests/ui/async-await/in-trait/async-recursive-generic.stderr @@ -0,0 +1,12 @@ +error[E0733]: recursion in an `async fn` requires boxing + --> $DIR/async-recursive-generic.rs:11:48 + | +LL | async fn foo_recursive(&self, n: usize) -> T { + | ^ recursive `async fn` + | + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` + = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0733`. diff --git a/tests/ui/async-await/in-trait/async-recursive.rs b/tests/ui/async-await/in-trait/async-recursive.rs index d928909e3ae..61119f8095b 100644 --- a/tests/ui/async-await/in-trait/async-recursive.rs +++ b/tests/ui/async-await/in-trait/async-recursive.rs @@ -1,6 +1,4 @@ // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/async-await/in-trait/async-recursive.stderr b/tests/ui/async-await/in-trait/async-recursive.stderr new file mode 100644 index 00000000000..9feff37b3fe --- /dev/null +++ b/tests/ui/async-await/in-trait/async-recursive.stderr @@ -0,0 +1,12 @@ +error[E0733]: recursion in an `async fn` requires boxing + --> $DIR/async-recursive.rs:11:48 + | +LL | async fn foo_recursive(&self, n: usize) -> i32 { + | ^^^ recursive `async fn` + | + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` + = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0733`. diff --git a/tests/ui/async-await/in-trait/bad-signatures.rs b/tests/ui/async-await/in-trait/bad-signatures.rs index 4baddd8ccb8..98dddc126c5 100644 --- a/tests/ui/async-await/in-trait/bad-signatures.rs +++ b/tests/ui/async-await/in-trait/bad-signatures.rs @@ -1,6 +1,4 @@ // edition:2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] diff --git a/tests/ui/async-await/in-trait/bad-signatures.stderr b/tests/ui/async-await/in-trait/bad-signatures.stderr new file mode 100644 index 00000000000..7cbd96e2487 --- /dev/null +++ b/tests/ui/async-await/in-trait/bad-signatures.stderr @@ -0,0 +1,17 @@ +error: expected identifier, found keyword `self` + --> $DIR/bad-signatures.rs:6:23 + | +LL | async fn bar(&abc self); + | ^^^^ expected identifier, found keyword + +error: expected one of `:`, `@`, or `|`, found keyword `self` + --> $DIR/bad-signatures.rs:6:23 + | +LL | async fn bar(&abc self); + | -----^^^^ + | | | + | | expected one of `:`, `@`, or `|` + | help: declare the type after the parameter binding: `: ` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs index 7183eaccc93..afd3db5e052 100644 --- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs +++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs @@ -1,7 +1,5 @@ // edition: 2021 // known-bug: #108309 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![feature(min_specialization)] diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr new file mode 100644 index 00000000000..7c750bf5101 --- /dev/null +++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr @@ -0,0 +1,25 @@ +error[E0053]: method `foo` has an incompatible type for trait + --> $DIR/dont-project-to-specializable-projection.rs:14:35 + | +LL | default async fn foo(_: T) -> &'static str { + | ^^^^^^^^^^^^ expected associated type, found future + | +note: type in trait + --> $DIR/dont-project-to-specializable-projection.rs:10:27 + | +LL | async fn foo(_: T) -> &'static str; + | ^^^^^^^^^^^^ + = note: expected signature `fn(_) -> impl Future` + found signature `fn(_) -> impl Future` + +error: async associated function in trait cannot be specialized + --> $DIR/dont-project-to-specializable-projection.rs:14:5 + | +LL | default async fn foo(_: T) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: specialization behaves in inconsistent and surprising ways with `#![feature(async_fn_in_trait)]`, and for now is disallowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/async-await/in-trait/early-bound-1.rs b/tests/ui/async-await/in-trait/early-bound-1.rs index 30843473def..6b3b142014b 100644 --- a/tests/ui/async-await/in-trait/early-bound-1.rs +++ b/tests/ui/async-await/in-trait/early-bound-1.rs @@ -1,7 +1,5 @@ // check-pass // edition:2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/async-await/in-trait/early-bound-2.rs b/tests/ui/async-await/in-trait/early-bound-2.rs index 1c5a68c2a5a..270443229b0 100644 --- a/tests/ui/async-await/in-trait/early-bound-2.rs +++ b/tests/ui/async-await/in-trait/early-bound-2.rs @@ -1,7 +1,5 @@ // check-pass // edition:2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.rs b/tests/ui/async-await/in-trait/fn-not-async-err2.rs index 5fdb7296aaf..78017429f73 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err2.rs +++ b/tests/ui/async-await/in-trait/fn-not-async-err2.rs @@ -1,6 +1,4 @@ // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.stderr b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr new file mode 100644 index 00000000000..37d9669c012 --- /dev/null +++ b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr @@ -0,0 +1,12 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return types + --> $DIR/fn-not-async-err2.rs:13:22 + | +LL | fn foo(&self) -> impl Future { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/async-await/in-trait/implied-bounds.rs b/tests/ui/async-await/in-trait/implied-bounds.rs index 45ada1d84c3..52bceb3cc5c 100644 --- a/tests/ui/async-await/in-trait/implied-bounds.rs +++ b/tests/ui/async-await/in-trait/implied-bounds.rs @@ -1,7 +1,5 @@ // check-pass // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/async-await/in-trait/issue-102138.rs b/tests/ui/async-await/in-trait/issue-102138.rs index ced30b7e4e4..f61b34ed99e 100644 --- a/tests/ui/async-await/in-trait/issue-102138.rs +++ b/tests/ui/async-await/in-trait/issue-102138.rs @@ -1,7 +1,5 @@ // check-pass // edition:2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/async-await/in-trait/issue-102219.rs b/tests/ui/async-await/in-trait/issue-102219.rs index f3fdfa3459a..9a35f6515cb 100644 --- a/tests/ui/async-await/in-trait/issue-102219.rs +++ b/tests/ui/async-await/in-trait/issue-102219.rs @@ -1,8 +1,6 @@ // compile-flags:--crate-type=lib // edition:2021 // check-pass -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/async-await/in-trait/issue-102310.rs b/tests/ui/async-await/in-trait/issue-102310.rs index 8e5dbd08eb9..49c3e9feeb4 100644 --- a/tests/ui/async-await/in-trait/issue-102310.rs +++ b/tests/ui/async-await/in-trait/issue-102310.rs @@ -1,7 +1,5 @@ // check-pass // edition:2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/async-await/in-trait/issue-104678.rs b/tests/ui/async-await/in-trait/issue-104678.rs index 3d010f18009..e396df4e5d1 100644 --- a/tests/ui/async-await/in-trait/issue-104678.rs +++ b/tests/ui/async-await/in-trait/issue-104678.rs @@ -1,7 +1,5 @@ // edition:2021 // check-pass -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/async-await/in-trait/lifetime-mismatch.rs b/tests/ui/async-await/in-trait/lifetime-mismatch.rs index 46183f72bce..bb793df5d85 100644 --- a/tests/ui/async-await/in-trait/lifetime-mismatch.rs +++ b/tests/ui/async-await/in-trait/lifetime-mismatch.rs @@ -1,6 +1,4 @@ // edition:2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] diff --git a/tests/ui/async-await/in-trait/lifetime-mismatch.stderr b/tests/ui/async-await/in-trait/lifetime-mismatch.stderr new file mode 100644 index 00000000000..86592269c02 --- /dev/null +++ b/tests/ui/async-await/in-trait/lifetime-mismatch.stderr @@ -0,0 +1,12 @@ +error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration + --> $DIR/lifetime-mismatch.rs:11:17 + | +LL | async fn foo<'a>(&self); + | ---- lifetimes in impl do not match this method in trait +... +LL | async fn foo(&self) {} + | ^ lifetimes do not match method in trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0195`. diff --git a/tests/ui/async-await/in-trait/missing-feature-flag.rs b/tests/ui/async-await/in-trait/missing-feature-flag.rs index 6481f4a7059..34dd50a1c30 100644 --- a/tests/ui/async-await/in-trait/missing-feature-flag.rs +++ b/tests/ui/async-await/in-trait/missing-feature-flag.rs @@ -1,6 +1,4 @@ // edition:2018 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] #![feature(min_specialization)] diff --git a/tests/ui/async-await/in-trait/missing-feature-flag.stderr b/tests/ui/async-await/in-trait/missing-feature-flag.stderr new file mode 100644 index 00000000000..f6aba1fcdbf --- /dev/null +++ b/tests/ui/async-await/in-trait/missing-feature-flag.stderr @@ -0,0 +1,30 @@ +error[E0046]: not all trait items implemented, missing: `foo` + --> $DIR/missing-feature-flag.rs:12:1 + | +LL | async fn foo(_: T) -> &'static str; + | ----------------------------------- `foo` from trait +... +LL | impl MyTrait for MyStruct {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/missing-feature-flag.rs:16:5 + | +LL | impl MyTrait for MyStruct {} + | ------------------------------- parent `impl` is here +... +LL | async fn foo(_: i32) -> &'static str {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error[E0308]: mismatched types + --> $DIR/missing-feature-flag.rs:16:42 + | +LL | async fn foo(_: i32) -> &'static str {} + | ^^ expected `&str`, found `()` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0046, E0308, E0520. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/async-await/in-trait/missing-send-bound.rs b/tests/ui/async-await/in-trait/missing-send-bound.rs index b602865cbb1..dbcc6657618 100644 --- a/tests/ui/async-await/in-trait/missing-send-bound.rs +++ b/tests/ui/async-await/in-trait/missing-send-bound.rs @@ -1,6 +1,4 @@ // edition:2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] diff --git a/tests/ui/async-await/in-trait/missing-send-bound.stderr b/tests/ui/async-await/in-trait/missing-send-bound.stderr new file mode 100644 index 00000000000..18185b75554 --- /dev/null +++ b/tests/ui/async-await/in-trait/missing-send-bound.stderr @@ -0,0 +1,20 @@ +error: future cannot be sent between threads safely + --> $DIR/missing-send-bound.rs:14:20 + | +LL | assert_is_send(test::()); + | ^^^^^^^^^^^ future returned by `test` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `impl Future` +note: future is not `Send` as it awaits another future which is not `Send` + --> $DIR/missing-send-bound.rs:10:5 + | +LL | T::bar().await; + | ^^^^^^^^ await occurs here on type `impl Future`, which is not `Send` +note: required by a bound in `assert_is_send` + --> $DIR/missing-send-bound.rs:18:27 + | +LL | fn assert_is_send(_: impl Send) {} + | ^^^^ required by this bound in `assert_is_send` + +error: aborting due to previous error + diff --git a/tests/ui/async-await/in-trait/object-safety.rs b/tests/ui/async-await/in-trait/object-safety.rs index 4edad1512e9..441539e5dd4 100644 --- a/tests/ui/async-await/in-trait/object-safety.rs +++ b/tests/ui/async-await/in-trait/object-safety.rs @@ -1,6 +1,4 @@ // edition:2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] diff --git a/tests/ui/async-await/in-trait/object-safety.stderr b/tests/ui/async-await/in-trait/object-safety.stderr new file mode 100644 index 00000000000..ccdf9d88708 --- /dev/null +++ b/tests/ui/async-await/in-trait/object-safety.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety.rs:10:12 + | +LL | let x: &dyn Foo = todo!(); + | ^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety.rs:6:14 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | async fn foo(&self); + | ^^^ ...because method `foo` is `async` + = help: consider moving `foo` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/async-await/in-trait/return-not-existing-pair.rs b/tests/ui/async-await/in-trait/return-not-existing-pair.rs index d1b3832d12b..a14dfceed75 100644 --- a/tests/ui/async-await/in-trait/return-not-existing-pair.rs +++ b/tests/ui/async-await/in-trait/return-not-existing-pair.rs @@ -1,6 +1,4 @@ // edition:2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] diff --git a/tests/ui/async-await/in-trait/return-not-existing-pair.stderr b/tests/ui/async-await/in-trait/return-not-existing-pair.stderr new file mode 100644 index 00000000000..e573b851706 --- /dev/null +++ b/tests/ui/async-await/in-trait/return-not-existing-pair.stderr @@ -0,0 +1,39 @@ +error[E0726]: implicit elided lifetime not allowed here + --> $DIR/return-not-existing-pair.rs:10:20 + | +LL | impl<'a, 'b, T, U> MyTrait for U { + | ^^^^^^^^^^ expected lifetime parameters + | +help: indicate the anonymous lifetimes + | +LL | impl<'a, 'b, T, U> MyTrait<'_, '_, T> for U { + | +++++++ + +error[E0412]: cannot find type `ConnImpl` in this scope + --> $DIR/return-not-existing-pair.rs:6:48 + | +LL | async fn foo(&'a self, key: &'b T) -> (&'a ConnImpl, &'b T); + | ^^^^^^^^ not found in this scope + +error[E0186]: method `foo` has a `&self` declaration in the trait, but not in the impl + --> $DIR/return-not-existing-pair.rs:12:5 + | +LL | async fn foo(&'a self, key: &'b T) -> (&'a ConnImpl, &'b T); + | ------------------------------------------------------------ `&self` used in trait +... +LL | async fn foo(_: T) -> (&'a U, &'b T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&self` in impl + +error[E0308]: mismatched types + --> $DIR/return-not-existing-pair.rs:12:42 + | +LL | async fn foo(_: T) -> (&'a U, &'b T) {} + | ^^ expected `(&U, &T)`, found `()` + | + = note: expected tuple `(&'a U, &'b T)` + found unit type `()` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0186, E0308, E0412, E0726. +For more information about an error, try `rustc --explain E0186`. diff --git a/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.rs b/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.rs index 37c02827e8d..254b9a7824f 100644 --- a/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.rs +++ b/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.rs @@ -1,6 +1,4 @@ // edition:2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_position_impl_trait_in_trait)] diff --git a/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.stderr b/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.stderr new file mode 100644 index 00000000000..059934d245c --- /dev/null +++ b/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/return-not-existing-type-wrapping-rpitit.rs:8:25 + | +LL | fn bar() -> Wrapper>; + | ^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.rs b/tests/ui/async-await/in-trait/return-type-suggestion.rs index d63bccefa9f..92a9e035e89 100644 --- a/tests/ui/async-await/in-trait/return-type-suggestion.rs +++ b/tests/ui/async-await/in-trait/return-type-suggestion.rs @@ -1,6 +1,4 @@ // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait)] diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.stderr b/tests/ui/async-await/in-trait/return-type-suggestion.stderr new file mode 100644 index 00000000000..d9309459812 --- /dev/null +++ b/tests/ui/async-await/in-trait/return-type-suggestion.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/return-type-suggestion.rs:7:9 + | +LL | Ok(()) + | ^^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found `Result<(), _>` + | + = note: expected unit type `()` + found enum `Result<(), _>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.rs b/tests/ui/async-await/return-type-notation/issue-110963-early.rs index eee31aa1fe5..0ecbca5c13b 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-early.rs +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.rs @@ -1,7 +1,5 @@ // edition: 2021 // known-bug: #110963 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_type_notation)] #![feature(async_fn_in_trait)] diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.stderr new file mode 100644 index 00000000000..33e22dec3f7 --- /dev/null +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.stderr @@ -0,0 +1,37 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-110963-early.rs:4:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: higher-ranked lifetime error + --> $DIR/issue-110963-early.rs:15:5 + | +LL | / spawn(async move { +LL | | let mut hc = hc; +LL | | if !hc.check().await { +LL | | log_health_check_failure().await; +LL | | } +LL | | }); + | |______^ + | + = note: could not prove `[async block@$DIR/issue-110963-early.rs:15:11: 20:6]: Send` + +error: higher-ranked lifetime error + --> $DIR/issue-110963-early.rs:15:5 + | +LL | / spawn(async move { +LL | | let mut hc = hc; +LL | | if !hc.check().await { +LL | | log_health_check_failure().await; +LL | | } +LL | | }); + | |______^ + | + = note: could not prove `[async block@$DIR/issue-110963-early.rs:15:11: 20:6]: Send` + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/async-await/return-type-notation/issue-110963-late.rs b/tests/ui/async-await/return-type-notation/issue-110963-late.rs index ea047cd3b16..17b5d775d44 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-late.rs +++ b/tests/ui/async-await/return-type-notation/issue-110963-late.rs @@ -1,7 +1,5 @@ // edition: 2021 // check-pass -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_type_notation)] //~^ WARN the feature `return_type_notation` is incomplete diff --git a/tests/ui/async-await/return-type-notation/issue-110963-late.stderr b/tests/ui/async-await/return-type-notation/issue-110963-late.stderr new file mode 100644 index 00000000000..9c6966537a7 --- /dev/null +++ b/tests/ui/async-await/return-type-notation/issue-110963-late.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-110963-late.rs:4:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/async-await/return-type-notation/super-method-bound.rs b/tests/ui/async-await/return-type-notation/super-method-bound.rs index 0163c62f545..58ea3578db6 100644 --- a/tests/ui/async-await/return-type-notation/super-method-bound.rs +++ b/tests/ui/async-await/return-type-notation/super-method-bound.rs @@ -1,7 +1,5 @@ // edition:2021 // check-pass -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait, return_type_notation)] //~^ WARN the feature `return_type_notation` is incomplete diff --git a/tests/ui/async-await/return-type-notation/super-method-bound.stderr b/tests/ui/async-await/return-type-notation/super-method-bound.stderr new file mode 100644 index 00000000000..ac0668d3c44 --- /dev/null +++ b/tests/ui/async-await/return-type-notation/super-method-bound.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/super-method-bound.rs:4:31 + | +LL | #![feature(async_fn_in_trait, return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/async-await/return-type-notation/supertrait-bound.rs b/tests/ui/async-await/return-type-notation/supertrait-bound.rs index 09de32c5d4a..19bcfe3046b 100644 --- a/tests/ui/async-await/return-type-notation/supertrait-bound.rs +++ b/tests/ui/async-await/return-type-notation/supertrait-bound.rs @@ -1,6 +1,4 @@ // check-pass -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_position_impl_trait_in_trait, return_type_notation)] //~^ WARN the feature `return_type_notation` is incomplete and may not be safe to use diff --git a/tests/ui/async-await/return-type-notation/supertrait-bound.stderr b/tests/ui/async-await/return-type-notation/supertrait-bound.stderr new file mode 100644 index 00000000000..c8cec4946b4 --- /dev/null +++ b/tests/ui/async-await/return-type-notation/supertrait-bound.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/supertrait-bound.rs:3:49 + | +LL | #![feature(return_position_impl_trait_in_trait, return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/async-await/return-type-notation/ty-or-ct-params.rs b/tests/ui/async-await/return-type-notation/ty-or-ct-params.rs index 3141da1d296..7871a2fed03 100644 --- a/tests/ui/async-await/return-type-notation/ty-or-ct-params.rs +++ b/tests/ui/async-await/return-type-notation/ty-or-ct-params.rs @@ -1,6 +1,4 @@ // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait, return_type_notation)] //~^ WARN the feature `return_type_notation` is incomplete diff --git a/tests/ui/async-await/return-type-notation/ty-or-ct-params.stderr b/tests/ui/async-await/return-type-notation/ty-or-ct-params.stderr new file mode 100644 index 00000000000..76928c5d7a3 --- /dev/null +++ b/tests/ui/async-await/return-type-notation/ty-or-ct-params.stderr @@ -0,0 +1,29 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/ty-or-ct-params.rs:3:31 + | +LL | #![feature(async_fn_in_trait, return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: return type notation is not allowed for functions that have type parameters + --> $DIR/ty-or-ct-params.rs:14:12 + | +LL | async fn bar() {} + | - type parameter declared here +... +LL | T: Foo, + | ^^^^^^^^^^^ + +error: return type notation is not allowed for functions that have const parameters + --> $DIR/ty-or-ct-params.rs:14:25 + | +LL | async fn baz() {} + | -------------- const parameter declared here +... +LL | T: Foo, + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.rs b/tests/ui/feature-gates/feature-gate-return_type_notation.rs index 7e8c1eb95ca..ae12495b5dc 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.rs +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.rs @@ -1,10 +1,7 @@ // edition: 2021 -// revisions: cfg_current cfg_next no_current no_next -// [cfg_next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// [no_next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: cfg no -// [no_current] check-pass -// [no_next] check-pass +// [no] check-pass // Since we're not adding new syntax, `cfg`'d out RTN must pass. #![feature(async_fn_in_trait)] @@ -13,17 +10,12 @@ trait Trait { async fn m(); } -#[cfg(any(cfg_current, cfg_next))] +#[cfg(cfg)] fn foo>() {} -//[cfg_current]~^ ERROR return type notation is experimental -//[cfg_current]~| ERROR parenthesized generic arguments cannot be used in associated type constraints -//[cfg_current]~| ERROR associated type `m` not found for `Trait` -//[cfg_next]~^^^^ ERROR return type notation is experimental -//[cfg_next]~| ERROR parenthesized generic arguments cannot be used in associated type constraints -//[cfg_next]~| ERROR associated type `m` not found for `Trait` -//[no_current]~^^^^^^^ WARN return type notation is experimental -//[no_current]~| WARN unstable syntax can change at any point in the future, causing a hard error! -//[no_next]~^^^^^^^^^ WARN return type notation is experimental -//[no_next]~| WARN unstable syntax can change at any point in the future, causing a hard error! +//[cfg]~^ ERROR return type notation is experimental +//[cfg]~| ERROR parenthesized generic arguments cannot be used in associated type constraints +//[cfg]~| ERROR associated type `m` not found for `Trait` +//[no]~^^^^ WARN return type notation is experimental +//[no]~| WARN unstable syntax can change at any point in the future, causing a hard error! fn main() {} diff --git a/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs b/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs index 776006124dc..cfc2193f633 100644 --- a/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs +++ b/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs @@ -1,5 +1,3 @@ -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty - #![feature(return_position_impl_trait_in_trait)] use std::ops::Deref; @@ -10,5 +8,7 @@ pub trait Foo { pub struct Foreign; impl Foo for Foreign { - fn bar(self) -> &'static () { &() } + fn bar(self) -> &'static () { + &() + } } diff --git a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs index f5290a5f4af..f5ee4690fa9 100644 --- a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs +++ b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs @@ -1,6 +1,4 @@ // check-pass -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_position_impl_trait_in_trait)] diff --git a/tests/ui/impl-trait/in-trait/deep-match-works.rs b/tests/ui/impl-trait/in-trait/deep-match-works.rs index 5c9d2e356fc..78cff97c616 100644 --- a/tests/ui/impl-trait/in-trait/deep-match-works.rs +++ b/tests/ui/impl-trait/in-trait/deep-match-works.rs @@ -1,6 +1,4 @@ // check-pass -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/deep-match.rs b/tests/ui/impl-trait/in-trait/deep-match.rs index 413d054e148..0cae88f349f 100644 --- a/tests/ui/impl-trait/in-trait/deep-match.rs +++ b/tests/ui/impl-trait/in-trait/deep-match.rs @@ -1,6 +1,3 @@ -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next - #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/deep-match.stderr b/tests/ui/impl-trait/in-trait/deep-match.stderr new file mode 100644 index 00000000000..f0ad3c16e9c --- /dev/null +++ b/tests/ui/impl-trait/in-trait/deep-match.stderr @@ -0,0 +1,15 @@ +error[E0053]: method `bar` has an incompatible return type for trait + --> $DIR/deep-match.rs:11:17 + | +LL | fn bar() -> i32 { + | ^^^ + | | + | expected `Wrapper<_>`, found `i32` + | return type in trait + | + = note: expected struct `Wrapper<_>` + found type `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs b/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs index 62323776310..45ae2b8ad3a 100644 --- a/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs +++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs @@ -1,6 +1,4 @@ // edition:2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![allow(incomplete_features)] #![feature(async_fn_in_trait)] diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr new file mode 100644 index 00000000000..cc3bdf0e571 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/default-body-type-err-2.rs:8:9 + | +LL | 42 + | ^^- help: try using a conversion method: `.to_string()` + | | + | expected `String`, found integer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.rs b/tests/ui/impl-trait/in-trait/default-body-type-err.rs index 9bd5b777989..ac9baf91cae 100644 --- a/tests/ui/impl-trait/in-trait/default-body-type-err.rs +++ b/tests/ui/impl-trait/in-trait/default-body-type-err.rs @@ -1,6 +1,3 @@ -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next - #![allow(incomplete_features)] #![feature(return_position_impl_trait_in_trait)] diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err.stderr new file mode 100644 index 00000000000..4742eb37d3e --- /dev/null +++ b/tests/ui/impl-trait/in-trait/default-body-type-err.stderr @@ -0,0 +1,12 @@ +error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String` + --> $DIR/default-body-type-err.rs:7:22 + | +LL | fn lol(&self) -> impl Deref { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String` +LL | +LL | &1i32 + | ----- return type was inferred to be `&i32` here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs index 6bcc7b9ef95..0558d95128f 100644 --- a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs +++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs @@ -1,7 +1,5 @@ // edition:2021 // known-bug: #108304 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr b/tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr new file mode 100644 index 00000000000..b5fc9d44d36 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr @@ -0,0 +1,24 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/default-body-with-rpit.rs:11:9 + | +LL | "" + | ^^ expected `impl Debug`, got `&'static str` + | +note: previous use here + --> $DIR/default-body-with-rpit.rs:10:39 + | +LL | async fn baz(&self) -> impl Debug { + | _______________________________________^ +LL | | "" +LL | | } + | |_____^ + +error[E0720]: cannot resolve opaque type + --> $DIR/default-body-with-rpit.rs:10:28 + | +LL | async fn baz(&self) -> impl Debug { + | ^^^^^^^^^^ cannot resolve opaque type + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/in-trait/default-body.rs b/tests/ui/impl-trait/in-trait/default-body.rs index ab6a51c6bcb..b0baf5bb10d 100644 --- a/tests/ui/impl-trait/in-trait/default-body.rs +++ b/tests/ui/impl-trait/in-trait/default-body.rs @@ -1,7 +1,5 @@ // check-pass // edition:2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs b/tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs index 187039f449c..817a4d7dbbe 100644 --- a/tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs +++ b/tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs @@ -1,6 +1,4 @@ // check-pass -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_position_impl_trait_in_trait)] diff --git a/tests/ui/impl-trait/in-trait/default-method-constraint.rs b/tests/ui/impl-trait/in-trait/default-method-constraint.rs index 4f0bf2e7dfe..28d76241f27 100644 --- a/tests/ui/impl-trait/in-trait/default-method-constraint.rs +++ b/tests/ui/impl-trait/in-trait/default-method-constraint.rs @@ -1,6 +1,4 @@ // check-pass -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next // This didn't work in the previous default RPITIT method hack attempt diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs b/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs index fcd0b51eea4..bb4e0d44f3e 100644 --- a/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs +++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs @@ -1,6 +1,3 @@ -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next - #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr new file mode 100644 index 00000000000..7c56ffa10e1 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr @@ -0,0 +1,17 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/doesnt-satisfy.rs:9:17 + | +LL | fn bar() -> () {} + | ^^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Foo::{opaque#0}` + --> $DIR/doesnt-satisfy.rs:5:22 + | +LL | fn bar() -> impl std::fmt::Display; + | ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs index 4d50b8c9278..4719d5d3c67 100644 --- a/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs +++ b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs @@ -1,6 +1,3 @@ -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next - #![feature(return_position_impl_trait_in_trait)] trait MyTrait { diff --git a/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.stderr b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.stderr new file mode 100644 index 00000000000..66ee142ccc4 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `foo` + --> $DIR/dont-project-to-rpitit-with-no-value.rs:8:1 + | +LL | fn foo(&self) -> impl Sized; + | ---------------------------- `foo` from trait +... +LL | impl MyTrait for i32 { + | ^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/impl-trait/in-trait/early.rs b/tests/ui/impl-trait/in-trait/early.rs index 831033a5880..9c1c2b50339 100644 --- a/tests/ui/impl-trait/in-trait/early.rs +++ b/tests/ui/impl-trait/in-trait/early.rs @@ -1,7 +1,5 @@ // check-pass // edition:2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/encode.rs b/tests/ui/impl-trait/in-trait/encode.rs index 98aaf4a6553..efb9f6498ba 100644 --- a/tests/ui/impl-trait/in-trait/encode.rs +++ b/tests/ui/impl-trait/in-trait/encode.rs @@ -1,7 +1,5 @@ // build-pass // compile-flags: --crate-type=lib -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr index 6eef392c05f..bfb2be8cbc1 100644 --- a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr +++ b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr @@ -5,7 +5,7 @@ LL | let _: &dyn rpitit::Foo = todo!(); | ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/auxiliary/rpitit.rs:8:21 + --> $DIR/auxiliary/rpitit.rs:6:21 | LL | fn bar(self) -> impl Deref; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait cannot be made into an object because method `bar` references an `impl Trait` type in its return type diff --git a/tests/ui/impl-trait/in-trait/foreign.rs b/tests/ui/impl-trait/in-trait/foreign.rs index b0fbe3a3d4a..b0c93a02935 100644 --- a/tests/ui/impl-trait/in-trait/foreign.rs +++ b/tests/ui/impl-trait/in-trait/foreign.rs @@ -1,7 +1,5 @@ // check-pass // aux-build: rpitit.rs -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next extern crate rpitit; @@ -11,7 +9,9 @@ use std::sync::Arc; // Implement an RPITIT from another crate. struct Local; impl Foo for Local { - fn bar(self) -> Arc { Arc::new(String::new()) } + fn bar(self) -> Arc { + Arc::new(String::new()) + } } fn generic(f: impl Foo) { diff --git a/tests/ui/impl-trait/in-trait/generics-mismatch.rs b/tests/ui/impl-trait/in-trait/generics-mismatch.rs index 9259ca193d1..cc0fc720ebb 100644 --- a/tests/ui/impl-trait/in-trait/generics-mismatch.rs +++ b/tests/ui/impl-trait/in-trait/generics-mismatch.rs @@ -1,6 +1,3 @@ -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next - #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/generics-mismatch.stderr b/tests/ui/impl-trait/in-trait/generics-mismatch.stderr new file mode 100644 index 00000000000..cd42683e022 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/generics-mismatch.stderr @@ -0,0 +1,12 @@ +error[E0049]: method `bar` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/generics-mismatch.rs:11:12 + | +LL | fn bar(&self) -> impl Sized; + | - expected 0 type parameters +... +LL | fn bar(&self) {} + | ^ found 1 type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/impl-trait/in-trait/issue-102140.rs b/tests/ui/impl-trait/in-trait/issue-102140.rs index 4dcac4f5b0e..be1e012acb1 100644 --- a/tests/ui/impl-trait/in-trait/issue-102140.rs +++ b/tests/ui/impl-trait/in-trait/issue-102140.rs @@ -1,6 +1,3 @@ -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next - #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/issue-102140.stderr b/tests/ui/impl-trait/in-trait/issue-102140.stderr new file mode 100644 index 00000000000..5d55b9fa4f9 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/issue-102140.stderr @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied + --> $DIR/issue-102140.rs:23:22 + | +LL | MyTrait::foo(&self) + | ------------ ^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` + | | + | required by a bound introduced by this call + | + = help: the trait `MyTrait` is implemented for `Outer` + +error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied + --> $DIR/issue-102140.rs:23:9 + | +LL | MyTrait::foo(&self) + | ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` + | + = help: the trait `MyTrait` is implemented for `Outer` + +error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied + --> $DIR/issue-102140.rs:23:9 + | +LL | MyTrait::foo(&self) + | ^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` + | + = help: the trait `MyTrait` is implemented for `Outer` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/issue-102301.rs b/tests/ui/impl-trait/in-trait/issue-102301.rs index 1329ca29d06..a93714a658e 100644 --- a/tests/ui/impl-trait/in-trait/issue-102301.rs +++ b/tests/ui/impl-trait/in-trait/issue-102301.rs @@ -1,6 +1,4 @@ // check-pass -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/issue-102571.rs b/tests/ui/impl-trait/in-trait/issue-102571.rs index f0ddab5e7f2..61c91e64417 100644 --- a/tests/ui/impl-trait/in-trait/issue-102571.rs +++ b/tests/ui/impl-trait/in-trait/issue-102571.rs @@ -1,6 +1,3 @@ -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next - #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/issue-102571.stderr b/tests/ui/impl-trait/in-trait/issue-102571.stderr new file mode 100644 index 00000000000..87219941d91 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/issue-102571.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-102571.rs:20:9 + | +LL | let () = t.bar(); + | ^^ ------- this expression has type `impl Deref` + | | + | expected associated type, found `()` + | + = note: expected associated type `impl Deref` + found unit type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/in-trait/nested-rpitit.rs b/tests/ui/impl-trait/in-trait/nested-rpitit.rs index 36020753726..65285e3a3cc 100644 --- a/tests/ui/impl-trait/in-trait/nested-rpitit.rs +++ b/tests/ui/impl-trait/in-trait/nested-rpitit.rs @@ -1,6 +1,4 @@ // check-pass -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/object-safety.rs b/tests/ui/impl-trait/in-trait/object-safety.rs index 016a0aaae4b..dd35b9a2d8a 100644 --- a/tests/ui/impl-trait/in-trait/object-safety.rs +++ b/tests/ui/impl-trait/in-trait/object-safety.rs @@ -1,6 +1,3 @@ -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next - #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/object-safety.stderr b/tests/ui/impl-trait/in-trait/object-safety.stderr new file mode 100644 index 00000000000..4a3b3b11465 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/object-safety.stderr @@ -0,0 +1,49 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety.rs:17:33 + | +LL | let i = Box::new(42_u32) as Box; + | ^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety.rs:7:22 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn baz(&self) -> impl Debug; + | ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type + = help: consider moving `baz` to another trait + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety.rs:20:13 + | +LL | let s = i.baz(); + | ^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety.rs:7:22 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn baz(&self) -> impl Debug; + | ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type + = help: consider moving `baz` to another trait + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety.rs:17:13 + | +LL | let i = Box::new(42_u32) as Box; + | ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety.rs:7:22 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn baz(&self) -> impl Debug; + | ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type + = help: consider moving `baz` to another trait + = note: required for the cast from `Box` to `Box` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs index c07ece15a83..3ac264e8eba 100644 --- a/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs +++ b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs @@ -1,6 +1,3 @@ -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next - #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr new file mode 100644 index 00000000000..15edda48340 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/opaque-in-impl-is-opaque.rs:17:19 + | +LL | fn bar(&self) -> impl Display { + | ------------ the found opaque type +... +LL | let x: &str = ().bar(); + | ---- ^^^^^^^^ expected `&str`, found opaque type + | | + | expected due to this + | + = note: expected reference `&str` + found opaque type `impl std::fmt::Display` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/in-trait/opaque-in-impl.rs b/tests/ui/impl-trait/in-trait/opaque-in-impl.rs index f48d9fa26c0..2e06629699a 100644 --- a/tests/ui/impl-trait/in-trait/opaque-in-impl.rs +++ b/tests/ui/impl-trait/in-trait/opaque-in-impl.rs @@ -1,6 +1,4 @@ // check-pass -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs index 65528f212e2..5d9a224ccd6 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs @@ -1,6 +1,3 @@ -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next - #![feature(return_position_impl_trait_in_trait)] trait Foo { diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr new file mode 100644 index 00000000000..668fc6cbe7f --- /dev/null +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `impl Foo: Foo` is not satisfied + --> $DIR/return-dont-satisfy-bounds.rs:10:34 + | +LL | fn foo>(self) -> impl Foo { + | ^^^^^^^^^^^^ the trait `Foo` is not implemented for `impl Foo` + | + = help: the trait `Foo` is implemented for `Bar` +note: required by a bound in `Foo::{opaque#0}` + --> $DIR/return-dont-satisfy-bounds.rs:4:30 + | +LL | fn foo(self) -> impl Foo; + | ^^^^^^ required by this bound in `Foo::{opaque#0}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/reveal.rs b/tests/ui/impl-trait/in-trait/reveal.rs index 1f42ec744db..d6ede1cc495 100644 --- a/tests/ui/impl-trait/in-trait/reveal.rs +++ b/tests/ui/impl-trait/in-trait/reveal.rs @@ -1,6 +1,4 @@ // check-pass -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.rs b/tests/ui/impl-trait/in-trait/signature-mismatch.rs index 23dd71acecb..1d63a6f3ce2 100644 --- a/tests/ui/impl-trait/in-trait/signature-mismatch.rs +++ b/tests/ui/impl-trait/in-trait/signature-mismatch.rs @@ -1,6 +1,4 @@ // edition:2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.stderr b/tests/ui/impl-trait/in-trait/signature-mismatch.stderr new file mode 100644 index 00000000000..616f1ac35a9 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/signature-mismatch.stderr @@ -0,0 +1,61 @@ +error: return type captures more lifetimes than trait definition + --> $DIR/signature-mismatch.rs:34:47 + | +LL | fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future> + 'a { + | -- this lifetime was captured ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: hidden type must only reference lifetimes captured by this impl trait + --> $DIR/signature-mismatch.rs:15:40 + | +LL | fn async_fn(&self, buff: &[u8]) -> impl Future>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: hidden type inferred to be `impl Future> + 'a` + +error: return type captures more lifetimes than trait definition + --> $DIR/signature-mismatch.rs:39:57 + | +LL | fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future> + 'a { + | -- this lifetime was captured ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: hidden type must only reference lifetimes captured by this impl trait + --> $DIR/signature-mismatch.rs:16:57 + | +LL | fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: hidden type inferred to be `impl Future> + 'a` + +error: return type captures more lifetimes than trait definition + --> $DIR/signature-mismatch.rs:47:10 + | +LL | fn async_fn_multiple<'a, 'b>( + | -- this lifetime was captured +... +LL | ) -> impl Future> + Captures2<'a, 'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: hidden type must only reference lifetimes captured by this impl trait + --> $DIR/signature-mismatch.rs:18:12 + | +LL | -> impl Future> + Captures<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: hidden type inferred to be `impl Future> + Captures2<'a, 'b>` + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/signature-mismatch.rs:56:10 + | +LL | ) -> impl Future> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `impl Future>` will meet its required lifetime bounds... + | +note: ...that is required by this bound + --> $DIR/signature-mismatch.rs:23:42 + | +LL | ) -> impl Future> + 'a; + | ^^ +help: consider adding an explicit lifetime bound... + | +LL | fn async_fn_reduce_outlive<'a, 'b, T: 'a>( + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.rs b/tests/ui/impl-trait/in-trait/specialization-broken.rs index 658d0709717..2fcffdf3f9a 100644 --- a/tests/ui/impl-trait/in-trait/specialization-broken.rs +++ b/tests/ui/impl-trait/in-trait/specialization-broken.rs @@ -1,6 +1,3 @@ -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next - // FIXME(compiler-errors): I'm not exactly sure if this is expected to pass or not. // But we fixed an ICE anyways. diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.stderr b/tests/ui/impl-trait/in-trait/specialization-broken.stderr new file mode 100644 index 00000000000..dc621d6b8a8 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/specialization-broken.stderr @@ -0,0 +1,31 @@ +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/specialization-broken.rs:16:22 + | +LL | default impl Foo for U + | - this type parameter +... +LL | fn bar(&self) -> U { + | ^ + | | + | expected associated type, found type parameter `U` + | help: change the output type to match the trait: `impl Sized` + | +note: type in trait + --> $DIR/specialization-broken.rs:9:22 + | +LL | fn bar(&self) -> impl Sized; + | ^^^^^^^^^^ + = note: expected signature `fn(&U) -> impl Sized` + found signature `fn(&U) -> U` + +error: method with return-position `impl Trait` in trait cannot be specialized + --> $DIR/specialization-broken.rs:16:5 + | +LL | fn bar(&self) -> U { + | ^^^^^^^^^^^^^^^^^^ + | + = note: specialization behaves in inconsistent and surprising ways with `#![feature(return_position_impl_trait_in_trait)]`, and for now is disallowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs b/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs index dbc5d38f192..c9ee877db8e 100644 --- a/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs +++ b/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs @@ -1,6 +1,4 @@ // check-pass -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(specialization)] #![feature(return_position_impl_trait_in_trait)] diff --git a/tests/ui/impl-trait/in-trait/success.rs b/tests/ui/impl-trait/in-trait/success.rs index 0e69e0490c7..4cbe682b46f 100644 --- a/tests/ui/impl-trait/in-trait/success.rs +++ b/tests/ui/impl-trait/in-trait/success.rs @@ -1,6 +1,4 @@ // check-pass -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs index c2e394a1f66..0bbe50ea6fd 100644 --- a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs +++ b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs @@ -1,6 +1,3 @@ -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next - #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr new file mode 100644 index 00000000000..8ff54cad951 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr @@ -0,0 +1,12 @@ +error[E0049]: method `bar` has 0 type parameters but its trait declaration has 1 type parameter + --> $DIR/trait-more-generics-than-impl.rs:11:11 + | +LL | fn bar() -> impl Sized; + | - expected 1 type parameter +... +LL | fn bar() -> impl Sized {} + | ^ found 0 type parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/impl-trait/in-trait/unconstrained-lt.rs b/tests/ui/impl-trait/in-trait/unconstrained-lt.rs index f966be43a6e..07c8606f9fe 100644 --- a/tests/ui/impl-trait/in-trait/unconstrained-lt.rs +++ b/tests/ui/impl-trait/in-trait/unconstrained-lt.rs @@ -1,6 +1,3 @@ -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next - #![feature(return_position_impl_trait_in_trait)] trait Foo { @@ -10,7 +7,9 @@ trait Foo { impl<'a, T> Foo for T { //~^ ERROR the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates - fn test() -> &'a () { &() } + fn test() -> &'a () { + &() + } } fn main() {} diff --git a/tests/ui/impl-trait/in-trait/unconstrained-lt.stderr b/tests/ui/impl-trait/in-trait/unconstrained-lt.stderr new file mode 100644 index 00000000000..cfce3556720 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/unconstrained-lt.stderr @@ -0,0 +1,9 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/unconstrained-lt.rs:7:6 + | +LL | impl<'a, T> Foo for T { + | ^^ unconstrained lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/impl-trait/in-trait/variances-of-gat.rs b/tests/ui/impl-trait/in-trait/variances-of-gat.rs index 4008ece94da..0d19e1ff416 100644 --- a/tests/ui/impl-trait/in-trait/variances-of-gat.rs +++ b/tests/ui/impl-trait/in-trait/variances-of-gat.rs @@ -1,6 +1,4 @@ // check-pass -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_position_impl_trait_in_trait)] diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.rs b/tests/ui/impl-trait/in-trait/wf-bounds.rs index f8c1e561d5c..ee873f94b26 100644 --- a/tests/ui/impl-trait/in-trait/wf-bounds.rs +++ b/tests/ui/impl-trait/in-trait/wf-bounds.rs @@ -1,6 +1,4 @@ // issue #101663 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.stderr b/tests/ui/impl-trait/in-trait/wf-bounds.stderr new file mode 100644 index 00000000000..beac6620911 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/wf-bounds.stderr @@ -0,0 +1,57 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/wf-bounds.rs:15:22 + | +LL | fn nya() -> impl Wf>; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/wf-bounds.rs:18:23 + | +LL | fn nya2() -> impl Wf<[u8]>; + | ^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `Wf` + --> $DIR/wf-bounds.rs:8:10 + | +LL | trait Wf { + | ^ required by this bound in `Wf` +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Wf { + | ++++++++ + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/wf-bounds.rs:21:44 + | +LL | fn nya3() -> impl Wf<(), Output = impl Wf>>; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error[E0277]: `T` doesn't implement `std::fmt::Display` + --> $DIR/wf-bounds.rs:24:26 + | +LL | fn nya4() -> impl Wf>; + | ^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter + | + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `NeedsDisplay` + --> $DIR/wf-bounds.rs:12:24 + | +LL | struct NeedsDisplay(T); + | ^^^^^^^ required by this bound in `NeedsDisplay` +help: consider restricting type parameter `T` + | +LL | fn nya4() -> impl Wf>; + | +++++++++++++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/where-clause.rs b/tests/ui/impl-trait/in-trait/where-clause.rs index 88d86e2b541..87bac519cf3 100644 --- a/tests/ui/impl-trait/in-trait/where-clause.rs +++ b/tests/ui/impl-trait/in-trait/where-clause.rs @@ -1,7 +1,5 @@ // check-pass // edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs index ca5fa6df2a6..77227ebd834 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs +++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs @@ -1,6 +1,3 @@ -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next - #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr new file mode 100644 index 00000000000..c4371a0024c --- /dev/null +++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `Something: Termination` is not satisfied + --> $DIR/issue-103052-2.rs:12:22 + | +LL | fn main() -> Something { + | ^^^^^^^^^ the trait `Termination` is not implemented for `Something` + | +note: required by a bound in `Main::{opaque#0}` + --> $DIR/issue-103052-2.rs:6:27 + | +LL | fn main() -> impl std::process::Termination; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{opaque#0}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 329e0994000ecdb5a3dfd468f08b37b67006647f Mon Sep 17 00:00:00 2001 From: Seth Junot Date: Sat, 8 Jul 2023 18:44:50 -0700 Subject: [PATCH 20/50] Support explicit 32-bit MIPS ABI for the synthetic object PR #95604 introduced a "synthetic object file to ensure all exported and used symbols participate in the linking". One constraint on this file is that for MIPS-based targets, its architecture-specific ELF flags must be the same as all other object files passed to the linker. That's enforced by LLD, here: https://github.com/llvm/llvm-project/blob/llvmorg-16.0.6/lld/ELF/Arch/MipsArchTree.cpp#L77 The current approach to determining e_flags for 32-bit was implemented in PR #96930, which links to this issue that summarizes the problem well: https://github.com/ayrtonm/psx-sdk-rs/issues/9 > ... the temporary object file is created with an e_flags which is > invalid for 32-bit MIPS targets. The main issue is that it omits the ABI > bits (EF_MIPS_ABI_O32) which implies it uses the N64 ABI. To enable the N32 MIPS ABI (which succeeded O32), this patch enables setting the synthetic object's ABI based on the target "llvm-abiname" field, if it's given; otherwise, the O32 ABI is assumed for 32-bit MIPS targets. More information about the N32 ABI can be found here: https://web.archive.org/web/20160121005457/http://techpubs.sgi.com/library/manuals/2000/007-2816-005/pdf/007-2816-005.pdf --- compiler/rustc_codegen_ssa/src/back/metadata.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 00e6acb5c1a..a463dff852d 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -243,8 +243,16 @@ pub(crate) fn create_object_file(sess: &Session) -> Option elf::EF_MIPS_ARCH_32R6, _ => elf::EF_MIPS_ARCH_32R2, }; - // The only ABI LLVM supports for 32-bit MIPS CPUs is o32. - let mut e_flags = elf::EF_MIPS_CPIC | elf::EF_MIPS_ABI_O32 | arch; + + let mut e_flags = elf::EF_MIPS_CPIC | arch; + + // If the ABI is explicitly given, use it or default to O32. + match sess.target.options.llvm_abiname.to_lowercase().as_str() { + "n32" => e_flags |= elf::EF_MIPS_ABI2, + "o32" => e_flags |= elf::EF_MIPS_ABI_O32, + _ => e_flags |= elf::EF_MIPS_ABI_O32, + }; + if sess.target.options.relocation_model != RelocModel::Static { e_flags |= elf::EF_MIPS_PIC; } From 7d7f6c544ea7ed8bb5ab00525799eb514ef83784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 10 Jul 2023 00:39:06 +0200 Subject: [PATCH 21/50] Don't label tracking issues with needs-triage --- triagebot.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index e6c593204ca..13e6d3ebe60 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -257,6 +257,9 @@ new_pr = true [autolabel."needs-triage"] new_issue = true +exclude_labels = [ + "C-tracking-issue" +] [autolabel."WG-trait-system-refactor"] trigger_files = [ From 0726c7826b81242d986e91535572935b9908b82f Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 10 Jul 2023 00:19:06 -0700 Subject: [PATCH 22/50] Reuse LLVMConstInBoundsGEP2 We have had LLVM 14 as our minimum for a bit now. --- compiler/rustc_codegen_llvm/src/common.rs | 4 ++-- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 +- compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 11 ----------- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index a2db59bd6c4..4d879fbdcb7 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -290,7 +290,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { } }; let llval = unsafe { - llvm::LLVMRustConstInBoundsGEP2( + llvm::LLVMConstInBoundsGEP2( self.type_i8(), self.const_bitcast(base_addr, self.type_i8p_ext(base_addr_space)), &self.const_usize(offset.bytes()), @@ -320,7 +320,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value { unsafe { - llvm::LLVMRustConstInBoundsGEP2( + llvm::LLVMConstInBoundsGEP2( self.type_i8(), self.const_bitcast(base_addr, self.type_i8p()), &self.const_usize(offset.bytes()), diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 3ad546b61e9..e1dfc1b2dd6 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1155,7 +1155,7 @@ extern "C" { pub fn LLVMConstVector(ScalarConstantVals: *const &Value, Size: c_uint) -> &Value; // Constant expressions - pub fn LLVMRustConstInBoundsGEP2<'a>( + pub fn LLVMConstInBoundsGEP2<'a>( ty: &'a Type, ConstantVal: &'a Value, ConstantIndices: *const &'a Value, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index bb7510b3a53..ab5fa961b95 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1616,17 +1616,6 @@ extern "C" void LLVMRustSetLinkage(LLVMValueRef V, LLVMSetLinkage(V, fromRust(RustLinkage)); } -// FIXME: replace with LLVMConstInBoundsGEP2 when bumped minimal version to llvm-14 -extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty, - LLVMValueRef ConstantVal, - LLVMValueRef *ConstantIndices, - unsigned NumIndices) { - ArrayRef IdxList(unwrap(ConstantIndices, NumIndices), - NumIndices); - Constant *Val = unwrap(ConstantVal); - return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList)); -} - extern "C" bool LLVMRustConstIntGetZExtValue(LLVMValueRef CV, uint64_t *value) { auto C = unwrap(CV); if (C->getBitWidth() > 64) From 470c244c8a8274e9969e873148f13fe23e64a2c4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 10 Jul 2023 08:25:50 +0000 Subject: [PATCH 23/50] Remove the library/term exception in tidy's pal checker code This crate doesn't exist anymore. --- src/tools/tidy/src/pal.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 62c070221dc..b386b000bef 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -39,7 +39,6 @@ const EXCEPTION_PATHS: &[&str] = &[ "library/panic_unwind", "library/unwind", "library/rtstartup", // Not sure what to do about this. magic stuff for mingw - "library/term", // Not sure how to make this crate portable, but test crate needs it. "library/test", // Probably should defer to unstable `std::sys` APIs. // The `VaList` implementation must have platform specific code. // The Windows implementation of a `va_list` is always a character From 68a381f38e97c3aef6e395841e4981f60785bba3 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 10 Jul 2023 09:02:47 -0700 Subject: [PATCH 24/50] Remove `rustc_llvm` from llvm-stamp nags LLVM is not *built* by `compiler/rustc_llvm` at all, only bindings on top of it, so there's no need to bump `download-ci-llvm-stamp` for that. --- triagebot.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 13e6d3ebe60..da9d167bd3e 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -486,10 +486,6 @@ message = "This PR changes src/bootstrap/defaults/config.codegen.toml. If approp [mentions."src/bootstrap/llvm.rs"] message = "This PR changes how LLVM is built. Consider updating src/bootstrap/download-ci-llvm-stamp." -[mentions."compiler/rustc_llvm/build.rs"] -message = "This PR changes how LLVM is built. Consider updating src/bootstrap/download-ci-llvm-stamp." -[mentions."compiler/rustc_llvm/llvm-wrapper"] -message = "This PR changes how LLVM is built. Consider updating src/bootstrap/download-ci-llvm-stamp." [mentions."tests/ui/deriving/deriving-all-codegen.stdout"] message = "Changes to the code generated for builtin derived traits." From f6d2bf63d3ce225a79dfdb9bab0f93568ad6e137 Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 17 May 2023 11:22:26 +0200 Subject: [PATCH 25/50] Uplift `clippy::fn_null_check` to rustc --- compiler/rustc_lint/messages.ftl | 3 + compiler/rustc_lint/src/fn_null_check.rs | 112 +++++++++++++++++++++++ compiler/rustc_lint/src/lib.rs | 3 + compiler/rustc_lint/src/lints.rs | 6 ++ tests/ui/lint/fn_null_check.rs | 30 ++++++ tests/ui/lint/fn_null_check.stderr | 67 ++++++++++++++ 6 files changed, 221 insertions(+) create mode 100644 compiler/rustc_lint/src/fn_null_check.rs create mode 100644 tests/ui/lint/fn_null_check.rs create mode 100644 tests/ui/lint/fn_null_check.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 34b7e09576a..2c92277b50d 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -215,6 +215,9 @@ lint_expectation = this lint expectation is unfulfilled .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message .rationale = {$rationale} +lint_fn_null_check = function pointers are not nullable, so checking them for null will always return false + .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + lint_for_loops_over_fallibles = for loop over {$article} `{$ty}`. This is more readably written as an `if let` statement .suggestion = consider using `if let` to clear intent diff --git a/compiler/rustc_lint/src/fn_null_check.rs b/compiler/rustc_lint/src/fn_null_check.rs new file mode 100644 index 00000000000..e3b33463ccf --- /dev/null +++ b/compiler/rustc_lint/src/fn_null_check.rs @@ -0,0 +1,112 @@ +use crate::{lints::FnNullCheckDiag, LateContext, LateLintPass, LintContext}; +use rustc_ast::LitKind; +use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind}; +use rustc_session::{declare_lint, declare_lint_pass}; +use rustc_span::sym; + +declare_lint! { + /// The `incorrect_fn_null_checks` lint checks for expression that checks if a + /// function pointer is null. + /// + /// ### Example + /// + /// ```rust + /// # fn test() {} + /// let fn_ptr: fn() = /* somehow obtained nullable function pointer */ + /// # test; + /// + /// if (fn_ptr as *const ()).is_null() { /* ... */ } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Function pointers are assumed to be non-null, checking them for null will always + /// return false. + INCORRECT_FN_NULL_CHECKS, + Warn, + "incorrect checking of null function pointer" +} + +declare_lint_pass!(IncorrectFnNullChecks => [INCORRECT_FN_NULL_CHECKS]); + +fn is_fn_ptr_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + let mut expr = expr.peel_blocks(); + let mut had_at_least_one_cast = false; + while let ExprKind::Cast(cast_expr, cast_ty) = expr.kind + && let TyKind::Ptr(_) = cast_ty.kind { + expr = cast_expr.peel_blocks(); + had_at_least_one_cast = true; + } + had_at_least_one_cast && cx.typeck_results().expr_ty_adjusted(expr).is_fn() +} + +impl<'tcx> LateLintPass<'tcx> for IncorrectFnNullChecks { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + match expr.kind { + // Catching: + // <* >::is_null(fn_ptr as * ) + ExprKind::Call(path, [arg]) + if let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && matches!( + cx.tcx.get_diagnostic_name(def_id), + Some(sym::ptr_const_is_null | sym::ptr_is_null) + ) + && is_fn_ptr_cast(cx, arg) => + { + cx.emit_spanned_lint(INCORRECT_FN_NULL_CHECKS, expr.span, FnNullCheckDiag) + } + + // Catching: + // (fn_ptr as * ).is_null() + ExprKind::MethodCall(_, receiver, _, _) + if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && matches!( + cx.tcx.get_diagnostic_name(def_id), + Some(sym::ptr_const_is_null | sym::ptr_is_null) + ) + && is_fn_ptr_cast(cx, receiver) => + { + cx.emit_spanned_lint(INCORRECT_FN_NULL_CHECKS, expr.span, FnNullCheckDiag) + } + + ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => { + let to_check: &Expr<'_>; + if is_fn_ptr_cast(cx, left) { + to_check = right; + } else if is_fn_ptr_cast(cx, right) { + to_check = left; + } else { + return; + } + + match to_check.kind { + // Catching: + // (fn_ptr as * ) == (0 as ) + ExprKind::Cast(cast_expr, _) + if let ExprKind::Lit(spanned) = cast_expr.kind + && let LitKind::Int(v, _) = spanned.node && v == 0 => + { + cx.emit_spanned_lint(INCORRECT_FN_NULL_CHECKS, expr.span, FnNullCheckDiag) + }, + + // Catching: + // (fn_ptr as * ) == std::ptr::null() + ExprKind::Call(path, []) + if let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id) + && (diag_item == sym::ptr_null || diag_item == sym::ptr_null_mut) => + { + cx.emit_spanned_lint(INCORRECT_FN_NULL_CHECKS, expr.span, FnNullCheckDiag) + }, + + _ => {}, + } + } + _ => {} + } + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 5e3f057d428..beb38dbb94c 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -58,6 +58,7 @@ mod early; mod enum_intrinsics_non_enums; mod errors; mod expect; +mod fn_null_check; mod for_loops_over_fallibles; pub mod hidden_unicode_codepoints; mod internal; @@ -102,6 +103,7 @@ use cast_ref_to_mut::*; use deref_into_dyn_supertrait::*; use drop_forget_useless::*; use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums; +use fn_null_check::*; use for_loops_over_fallibles::*; use hidden_unicode_codepoints::*; use internal::*; @@ -225,6 +227,7 @@ late_lint_methods!( // Depends on types used in type definitions MissingCopyImplementations: MissingCopyImplementations, // Depends on referenced function signatures in expressions + IncorrectFnNullChecks: IncorrectFnNullChecks, MutableTransmutes: MutableTransmutes, TypeAliasBounds: TypeAliasBounds, TrivialConstraints: TrivialConstraints, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 0613ef2c5e9..1dea758bb29 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -613,6 +613,12 @@ pub struct ExpectationNote { pub rationale: Symbol, } +// fn_null_check.rs +#[derive(LintDiagnostic)] +#[diag(lint_fn_null_check)] +#[help] +pub struct FnNullCheckDiag; + // for_loops_over_fallibles.rs #[derive(LintDiagnostic)] #[diag(lint_for_loops_over_fallibles)] diff --git a/tests/ui/lint/fn_null_check.rs b/tests/ui/lint/fn_null_check.rs new file mode 100644 index 00000000000..7f01f2c4283 --- /dev/null +++ b/tests/ui/lint/fn_null_check.rs @@ -0,0 +1,30 @@ +// check-pass + +fn main() { + let fn_ptr = main; + + if (fn_ptr as *mut ()).is_null() {} + //~^ WARN function pointers are not nullable + if (fn_ptr as *const u8).is_null() {} + //~^ WARN function pointers are not nullable + if (fn_ptr as *const ()) == std::ptr::null() {} + //~^ WARN function pointers are not nullable + if (fn_ptr as *mut ()) == std::ptr::null_mut() {} + //~^ WARN function pointers are not nullable + if (fn_ptr as *const ()) == (0 as *const ()) {} + //~^ WARN function pointers are not nullable + if <*const _>::is_null(fn_ptr as *const ()) {} + //~^ WARN function pointers are not nullable + if (fn_ptr as *mut fn() as *const fn() as *const ()).is_null() {} + //~^ WARN function pointers are not nullable + if (fn_ptr as fn() as *const ()).is_null() {} + //~^ WARN function pointers are not nullable + + const ZPTR: *const () = 0 as *const _; + const NOT_ZPTR: *const () = 1 as *const _; + + // unlike the uplifted clippy::fn_null_check lint we do + // not lint on them + if (fn_ptr as *const ()) == ZPTR {} + if (fn_ptr as *const ()) == NOT_ZPTR {} +} diff --git a/tests/ui/lint/fn_null_check.stderr b/tests/ui/lint/fn_null_check.stderr new file mode 100644 index 00000000000..0398c0da50f --- /dev/null +++ b/tests/ui/lint/fn_null_check.stderr @@ -0,0 +1,67 @@ +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/fn_null_check.rs:6:8 + | +LL | if (fn_ptr as *mut ()).is_null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + = note: `#[warn(incorrect_fn_null_checks)]` on by default + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/fn_null_check.rs:8:8 + | +LL | if (fn_ptr as *const u8).is_null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/fn_null_check.rs:10:8 + | +LL | if (fn_ptr as *const ()) == std::ptr::null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/fn_null_check.rs:12:8 + | +LL | if (fn_ptr as *mut ()) == std::ptr::null_mut() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/fn_null_check.rs:14:8 + | +LL | if (fn_ptr as *const ()) == (0 as *const ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/fn_null_check.rs:16:8 + | +LL | if <*const _>::is_null(fn_ptr as *const ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/fn_null_check.rs:18:8 + | +LL | if (fn_ptr as *mut fn() as *const fn() as *const ()).is_null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/fn_null_check.rs:20:8 + | +LL | if (fn_ptr as fn() as *const ()).is_null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: 8 warnings emitted + From c0fbeeab1697d52b47fad4fff73ac3f334b85562 Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 17 May 2023 20:01:36 +0200 Subject: [PATCH 26/50] Drop uplifted `clippy::fn_null_check` --- .../clippy/clippy_lints/src/declared_lints.rs | 1 - .../clippy/clippy_lints/src/fn_null_check.rs | 102 ---------------- src/tools/clippy/clippy_lints/src/lib.rs | 2 - .../clippy/clippy_lints/src/renamed_lints.rs | 1 + src/tools/clippy/tests/ui/fn_null_check.rs | 22 ---- .../clippy/tests/ui/fn_null_check.stderr | 43 ------- src/tools/clippy/tests/ui/rename.fixed | 2 + src/tools/clippy/tests/ui/rename.rs | 2 + src/tools/clippy/tests/ui/rename.stderr | 112 +++++++++--------- 9 files changed, 64 insertions(+), 223 deletions(-) delete mode 100644 src/tools/clippy/clippy_lints/src/fn_null_check.rs delete mode 100644 src/tools/clippy/tests/ui/fn_null_check.rs delete mode 100644 src/tools/clippy/tests/ui/fn_null_check.stderr diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 9d9ee6ba307..b60f0738f64 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -171,7 +171,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::float_literal::LOSSY_FLOAT_LITERAL_INFO, crate::floating_point_arithmetic::IMPRECISE_FLOPS_INFO, crate::floating_point_arithmetic::SUBOPTIMAL_FLOPS_INFO, - crate::fn_null_check::FN_NULL_CHECK_INFO, crate::format::USELESS_FORMAT_INFO, crate::format_args::FORMAT_IN_FORMAT_ARGS_INFO, crate::format_args::TO_STRING_IN_FORMAT_ARGS_INFO, diff --git a/src/tools/clippy/clippy_lints/src/fn_null_check.rs b/src/tools/clippy/clippy_lints/src/fn_null_check.rs deleted file mode 100644 index 521045a9fed..00000000000 --- a/src/tools/clippy/clippy_lints/src/fn_null_check.rs +++ /dev/null @@ -1,102 +0,0 @@ -use clippy_utils::consts::{constant, Constant}; -use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::{is_integer_literal, is_path_diagnostic_item}; -use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::sym; - -declare_clippy_lint! { - /// ### What it does - /// Checks for comparing a function pointer to null. - /// - /// ### Why is this bad? - /// Function pointers are assumed to not be null. - /// - /// ### Example - /// ```rust,ignore - /// let fn_ptr: fn() = /* somehow obtained nullable function pointer */ - /// - /// if (fn_ptr as *const ()).is_null() { ... } - /// ``` - /// Use instead: - /// ```rust,ignore - /// let fn_ptr: Option = /* somehow obtained nullable function pointer */ - /// - /// if fn_ptr.is_none() { ... } - /// ``` - #[clippy::version = "1.68.0"] - pub FN_NULL_CHECK, - correctness, - "`fn()` type assumed to be nullable" -} -declare_lint_pass!(FnNullCheck => [FN_NULL_CHECK]); - -fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) { - span_lint_and_help( - cx, - FN_NULL_CHECK, - expr.span, - "function pointer assumed to be nullable, even though it isn't", - None, - "try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value", - ); -} - -fn is_fn_ptr_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - if let ExprKind::Cast(cast_expr, cast_ty) = expr.kind - && let TyKind::Ptr(_) = cast_ty.kind - { - cx.typeck_results().expr_ty_adjusted(cast_expr).is_fn() - } else { - false - } -} - -impl<'tcx> LateLintPass<'tcx> for FnNullCheck { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - match expr.kind { - // Catching: - // (fn_ptr as * ).is_null() - ExprKind::MethodCall(method_name, receiver, _, _) - if method_name.ident.as_str() == "is_null" && is_fn_ptr_cast(cx, receiver) => - { - lint_expr(cx, expr); - }, - - ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => { - let to_check: &Expr<'_>; - if is_fn_ptr_cast(cx, left) { - to_check = right; - } else if is_fn_ptr_cast(cx, right) { - to_check = left; - } else { - return; - } - - match to_check.kind { - // Catching: - // (fn_ptr as * ) == (0 as ) - ExprKind::Cast(cast_expr, _) if is_integer_literal(cast_expr, 0) => { - lint_expr(cx, expr); - }, - - // Catching: - // (fn_ptr as * ) == std::ptr::null() - ExprKind::Call(func, []) if is_path_diagnostic_item(cx, func, sym::ptr_null) => { - lint_expr(cx, expr); - }, - - // Catching: - // (fn_ptr as * ) == - _ if matches!(constant(cx, cx.typeck_results(), to_check), Some(Constant::RawPtr(0))) => { - lint_expr(cx, expr); - }, - - _ => {}, - } - }, - _ => {}, - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 87329ee5e14..365cc4c59ad 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -131,7 +131,6 @@ mod extra_unused_type_parameters; mod fallible_impl_from; mod float_literal; mod floating_point_arithmetic; -mod fn_null_check; mod format; mod format_args; mod format_impl; @@ -1003,7 +1002,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: semicolon_outside_block_ignore_multiline, )) }); - store.register_late_pass(|_| Box::new(fn_null_check::FnNullCheck)); store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse)); store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef)); store.register_late_pass(|_| Box::new(multiple_unsafe_ops_per_block::MultipleUnsafeOpsPerBlock)); diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs index cbcd11debfd..d24215c2292 100644 --- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs +++ b/src/tools/clippy/clippy_lints/src/renamed_lints.rs @@ -42,6 +42,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[ ("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"), ("clippy::forget_copy", "forgetting_copy_types"), ("clippy::forget_ref", "forgetting_references"), + ("clippy::fn_null_check", "incorrect_fn_null_checks"), ("clippy::into_iter_on_array", "array_into_iter"), ("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"), ("clippy::invalid_ref", "invalid_value"), diff --git a/src/tools/clippy/tests/ui/fn_null_check.rs b/src/tools/clippy/tests/ui/fn_null_check.rs deleted file mode 100644 index dfdea100c8f..00000000000 --- a/src/tools/clippy/tests/ui/fn_null_check.rs +++ /dev/null @@ -1,22 +0,0 @@ -#![allow(unused)] -#![warn(clippy::fn_null_check)] -#![allow(clippy::cmp_null)] -#![allow(clippy::needless_if)] -#![allow(clippy::ptr_eq)] -#![allow(clippy::zero_ptr)] - -pub const ZPTR: *const () = 0 as *const _; -pub const NOT_ZPTR: *const () = 1 as *const _; - -fn main() { - let fn_ptr = main; - - if (fn_ptr as *mut ()).is_null() {} - if (fn_ptr as *const u8).is_null() {} - if (fn_ptr as *const ()) == std::ptr::null() {} - if (fn_ptr as *const ()) == (0 as *const ()) {} - if (fn_ptr as *const ()) == ZPTR {} - - // no lint - if (fn_ptr as *const ()) == NOT_ZPTR {} -} diff --git a/src/tools/clippy/tests/ui/fn_null_check.stderr b/src/tools/clippy/tests/ui/fn_null_check.stderr deleted file mode 100644 index 5b9f48a961c..00000000000 --- a/src/tools/clippy/tests/ui/fn_null_check.stderr +++ /dev/null @@ -1,43 +0,0 @@ -error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:14:8 - | -LL | if (fn_ptr as *mut ()).is_null() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value - = note: `-D clippy::fn-null-check` implied by `-D warnings` - -error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:15:8 - | -LL | if (fn_ptr as *const u8).is_null() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value - -error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:16:8 - | -LL | if (fn_ptr as *const ()) == std::ptr::null() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value - -error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:17:8 - | -LL | if (fn_ptr as *const ()) == (0 as *const ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value - -error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:18:8 - | -LL | if (fn_ptr as *const ()) == ZPTR {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value - -error: aborting due to 5 previous errors - diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed index b24c83d9a0d..cab02bb93c9 100644 --- a/src/tools/clippy/tests/ui/rename.fixed +++ b/src/tools/clippy/tests/ui/rename.fixed @@ -37,6 +37,7 @@ #![allow(for_loops_over_fallibles)] #![allow(forgetting_copy_types)] #![allow(forgetting_references)] +#![allow(incorrect_fn_null_checks)] #![allow(array_into_iter)] #![allow(invalid_atomic_ordering)] #![allow(invalid_value)] @@ -89,6 +90,7 @@ #![warn(for_loops_over_fallibles)] #![warn(forgetting_copy_types)] #![warn(forgetting_references)] +#![warn(incorrect_fn_null_checks)] #![warn(array_into_iter)] #![warn(invalid_atomic_ordering)] #![warn(invalid_value)] diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs index baa6345a64f..e5e31452149 100644 --- a/src/tools/clippy/tests/ui/rename.rs +++ b/src/tools/clippy/tests/ui/rename.rs @@ -37,6 +37,7 @@ #![allow(for_loops_over_fallibles)] #![allow(forgetting_copy_types)] #![allow(forgetting_references)] +#![allow(incorrect_fn_null_checks)] #![allow(array_into_iter)] #![allow(invalid_atomic_ordering)] #![allow(invalid_value)] @@ -89,6 +90,7 @@ #![warn(clippy::for_loops_over_fallibles)] #![warn(clippy::forget_copy)] #![warn(clippy::forget_ref)] +#![warn(clippy::fn_null_check)] #![warn(clippy::into_iter_on_array)] #![warn(clippy::invalid_atomic_ordering)] #![warn(clippy::invalid_ref)] diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr index ae25c3b46bd..783608a0841 100644 --- a/src/tools/clippy/tests/ui/rename.stderr +++ b/src/tools/clippy/tests/ui/rename.stderr @@ -1,5 +1,5 @@ error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range` - --> $DIR/rename.rs:52:9 + --> $DIR/rename.rs:53:9 | LL | #![warn(clippy::almost_complete_letter_range)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` @@ -7,310 +7,316 @@ LL | #![warn(clippy::almost_complete_letter_range)] = note: `-D renamed-and-removed-lints` implied by `-D warnings` error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names` - --> $DIR/rename.rs:53:9 + --> $DIR/rename.rs:54:9 | LL | #![warn(clippy::blacklisted_name)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names` error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions` - --> $DIR/rename.rs:54:9 + --> $DIR/rename.rs:55:9 | LL | #![warn(clippy::block_in_if_condition_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions` - --> $DIR/rename.rs:55:9 + --> $DIR/rename.rs:56:9 | LL | #![warn(clippy::block_in_if_condition_stmt)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::box_vec` has been renamed to `clippy::box_collection` - --> $DIR/rename.rs:56:9 + --> $DIR/rename.rs:57:9 | LL | #![warn(clippy::box_vec)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection` error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` - --> $DIR/rename.rs:57:9 + --> $DIR/rename.rs:58:9 | LL | #![warn(clippy::const_static_lifetime)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes` error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity` - --> $DIR/rename.rs:58:9 + --> $DIR/rename.rs:59:9 | LL | #![warn(clippy::cyclomatic_complexity)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity` error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq` - --> $DIR/rename.rs:59:9 + --> $DIR/rename.rs:60:9 | LL | #![warn(clippy::derive_hash_xor_eq)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq` error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods` - --> $DIR/rename.rs:60:9 + --> $DIR/rename.rs:61:9 | LL | #![warn(clippy::disallowed_method)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods` error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types` - --> $DIR/rename.rs:61:9 + --> $DIR/rename.rs:62:9 | LL | #![warn(clippy::disallowed_type)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types` error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression` - --> $DIR/rename.rs:62:9 + --> $DIR/rename.rs:63:9 | LL | #![warn(clippy::eval_order_dependence)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression` error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion` - --> $DIR/rename.rs:63:9 + --> $DIR/rename.rs:64:9 | LL | #![warn(clippy::identity_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion` error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok` - --> $DIR/rename.rs:64:9 + --> $DIR/rename.rs:65:9 | LL | #![warn(clippy::if_let_some_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects` - --> $DIR/rename.rs:65:9 + --> $DIR/rename.rs:66:9 | LL | #![warn(clippy::integer_arithmetic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects` error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr` - --> $DIR/rename.rs:66:9 + --> $DIR/rename.rs:67:9 | LL | #![warn(clippy::logic_bug)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr` error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` - --> $DIR/rename.rs:67:9 + --> $DIR/rename.rs:68:9 | LL | #![warn(clippy::new_without_default_derive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map` - --> $DIR/rename.rs:68:9 + --> $DIR/rename.rs:69:9 | LL | #![warn(clippy::option_and_then_some)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map` error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used` - --> $DIR/rename.rs:69:9 + --> $DIR/rename.rs:70:9 | LL | #![warn(clippy::option_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:70:9 + --> $DIR/rename.rs:71:9 | LL | #![warn(clippy::option_map_unwrap_or)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:71:9 + --> $DIR/rename.rs:72:9 | LL | #![warn(clippy::option_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used` - --> $DIR/rename.rs:72:9 + --> $DIR/rename.rs:73:9 | LL | #![warn(clippy::option_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow` - --> $DIR/rename.rs:73:9 + --> $DIR/rename.rs:74:9 | LL | #![warn(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow` error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used` - --> $DIR/rename.rs:74:9 + --> $DIR/rename.rs:75:9 | LL | #![warn(clippy::result_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:75:9 + --> $DIR/rename.rs:76:9 | LL | #![warn(clippy::result_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used` - --> $DIR/rename.rs:76:9 + --> $DIR/rename.rs:77:9 | LL | #![warn(clippy::result_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str` - --> $DIR/rename.rs:77:9 + --> $DIR/rename.rs:78:9 | LL | #![warn(clippy::single_char_push_str)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str` error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` - --> $DIR/rename.rs:78:9 + --> $DIR/rename.rs:79:9 | LL | #![warn(clippy::stutter)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl` - --> $DIR/rename.rs:79:9 + --> $DIR/rename.rs:80:9 | LL | #![warn(clippy::to_string_in_display)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl` error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters` - --> $DIR/rename.rs:80:9 + --> $DIR/rename.rs:81:9 | LL | #![warn(clippy::zero_width_space)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters` error: lint `clippy::cast_ref_to_mut` has been renamed to `cast_ref_to_mut` - --> $DIR/rename.rs:81:9 + --> $DIR/rename.rs:82:9 | LL | #![warn(clippy::cast_ref_to_mut)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `cast_ref_to_mut` error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op` - --> $DIR/rename.rs:82:9 + --> $DIR/rename.rs:83:9 | LL | #![warn(clippy::clone_double_ref)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op` error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons` - --> $DIR/rename.rs:83:9 + --> $DIR/rename.rs:84:9 | LL | #![warn(clippy::cmp_nan)] | ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons` error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` - --> $DIR/rename.rs:84:9 + --> $DIR/rename.rs:85:9 | LL | #![warn(clippy::drop_bounds)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types` - --> $DIR/rename.rs:85:9 + --> $DIR/rename.rs:86:9 | LL | #![warn(clippy::drop_copy)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types` error: lint `clippy::drop_ref` has been renamed to `dropping_references` - --> $DIR/rename.rs:86:9 + --> $DIR/rename.rs:87:9 | LL | #![warn(clippy::drop_ref)] | ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:87:9 + --> $DIR/rename.rs:88:9 | LL | #![warn(clippy::for_loop_over_option)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:88:9 + --> $DIR/rename.rs:89:9 | LL | #![warn(clippy::for_loop_over_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:89:9 + --> $DIR/rename.rs:90:9 | LL | #![warn(clippy::for_loops_over_fallibles)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types` - --> $DIR/rename.rs:90:9 + --> $DIR/rename.rs:91:9 | LL | #![warn(clippy::forget_copy)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types` error: lint `clippy::forget_ref` has been renamed to `forgetting_references` - --> $DIR/rename.rs:91:9 + --> $DIR/rename.rs:92:9 | LL | #![warn(clippy::forget_ref)] | ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references` +error: lint `clippy::fn_null_check` has been renamed to `incorrect_fn_null_checks` + --> $DIR/rename.rs:93:9 + | +LL | #![warn(clippy::fn_null_check)] + | ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `incorrect_fn_null_checks` + error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` - --> $DIR/rename.rs:92:9 + --> $DIR/rename.rs:94:9 | LL | #![warn(clippy::into_iter_on_array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter` error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering` - --> $DIR/rename.rs:93:9 + --> $DIR/rename.rs:95:9 | LL | #![warn(clippy::invalid_atomic_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering` error: lint `clippy::invalid_ref` has been renamed to `invalid_value` - --> $DIR/rename.rs:94:9 + --> $DIR/rename.rs:96:9 | LL | #![warn(clippy::invalid_ref)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked` - --> $DIR/rename.rs:95:9 + --> $DIR/rename.rs:97:9 | LL | #![warn(clippy::invalid_utf8_in_unchecked)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked` error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` - --> $DIR/rename.rs:96:9 + --> $DIR/rename.rs:98:9 | LL | #![warn(clippy::let_underscore_drop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop` error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` - --> $DIR/rename.rs:97:9 + --> $DIR/rename.rs:99:9 | LL | #![warn(clippy::mem_discriminant_non_enum)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` - --> $DIR/rename.rs:98:9 + --> $DIR/rename.rs:100:9 | LL | #![warn(clippy::panic_params)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally` - --> $DIR/rename.rs:99:9 + --> $DIR/rename.rs:101:9 | LL | #![warn(clippy::positional_named_format_parameters)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally` error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr` - --> $DIR/rename.rs:100:9 + --> $DIR/rename.rs:102:9 | LL | #![warn(clippy::temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr` error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops` - --> $DIR/rename.rs:101:9 + --> $DIR/rename.rs:103:9 | LL | #![warn(clippy::undropped_manually_drops)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops` error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` - --> $DIR/rename.rs:102:9 + --> $DIR/rename.rs:104:9 | LL | #![warn(clippy::unknown_clippy_lints)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` error: lint `clippy::unused_label` has been renamed to `unused_labels` - --> $DIR/rename.rs:103:9 + --> $DIR/rename.rs:105:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` -error: aborting due to 52 previous errors +error: aborting due to 53 previous errors From 44d0fce1504a570260deebdadb3b5fcf59eea940 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Tue, 20 Jun 2023 10:32:12 -0700 Subject: [PATCH 27/50] Fix standalone build Add extern declarations and optional dependencies to fix build done directly via `cargo build`. --- Cargo.lock | 1 + compiler/rustc_smir/Cargo.toml | 6 +++++- compiler/rustc_smir/rust-toolchain.toml | 2 +- compiler/rustc_smir/src/lib.rs | 10 ++++++++++ 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96eda77abb2..f880fb9bafb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4235,6 +4235,7 @@ dependencies = [ "rustc_middle", "rustc_span", "scoped-tls", + "rustc_target", "tracing", ] diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index a6e6de5f785..80d4e7ed02f 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -4,14 +4,18 @@ version = "0.0.0" edition = "2021" [dependencies] -rustc_hir = { path = "../rustc_hir" } +# Use optional dependencies for rustc_* in order to support building this crate separately. +rustc_hir = { path = "../rustc_hir", optional = true } rustc_middle = { path = "../rustc_middle", optional = true } rustc_span = { path = "../rustc_span", optional = true } +rustc_target = { path = "../rustc_target", optional = true } tracing = "0.1" scoped-tls = "1.0" [features] default = [ + "rustc_hir", "rustc_middle", "rustc_span", + "rustc_target", ] diff --git a/compiler/rustc_smir/rust-toolchain.toml b/compiler/rustc_smir/rust-toolchain.toml index 157dfd620ee..d75e8e33b1c 100644 --- a/compiler/rustc_smir/rust-toolchain.toml +++ b/compiler/rustc_smir/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-02-28" +channel = "nightly-2023-06-14" components = [ "rustfmt", "rustc-dev" ] diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index fb03633b99b..21c72f3aaa1 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -14,6 +14,16 @@ #![feature(local_key_cell_methods)] #![feature(ptr_metadata)] +// Declare extern rustc_* crates to enable building this crate separately from the compiler. +#[cfg(not(feature = "default"))] +extern crate rustc_hir; +#[cfg(not(feature = "default"))] +extern crate rustc_middle; +#[cfg(not(feature = "default"))] +extern crate rustc_span; +#[cfg(not(feature = "default"))] +extern crate rustc_target; + pub mod rustc_internal; pub mod stable_mir; From 697563289d18ba54aa96ec9ba8f9f716d095ce46 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Tue, 20 Jun 2023 10:40:23 -0700 Subject: [PATCH 28/50] Implement Stable for AssertMessage --- compiler/rustc_smir/src/rustc_smir/mod.rs | 67 +++++++++++++---------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 85d5bb00c4e..8a6153269a1 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -137,8 +137,11 @@ fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate { stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local } } -pub trait Stable { +/// Trait used to convert between an internal MIR type to a Stable MIR type. +pub(crate) trait Stable { + /// The stable representation of the type implementing Stable. type T; + /// Converts an object to the equivalent Stable MIR representation. fn stable(&self) -> Self::T; } @@ -229,34 +232,38 @@ impl Stable for mir::UnwindAction { } } -fn rustc_assert_msg_to_msg<'tcx>( - assert_message: &rustc_middle::mir::AssertMessage<'tcx>, -) -> stable_mir::mir::AssertMessage { - use rustc_middle::mir::AssertKind; - match assert_message { - AssertKind::BoundsCheck { len, index } => { - stable_mir::mir::AssertMessage::BoundsCheck { len: len.stable(), index: index.stable() } - } - AssertKind::Overflow(bin_op, op1, op2) => { - stable_mir::mir::AssertMessage::Overflow(bin_op.stable(), op1.stable(), op2.stable()) - } - AssertKind::OverflowNeg(op) => stable_mir::mir::AssertMessage::OverflowNeg(op.stable()), - AssertKind::DivisionByZero(op) => { - stable_mir::mir::AssertMessage::DivisionByZero(op.stable()) - } - AssertKind::RemainderByZero(op) => { - stable_mir::mir::AssertMessage::RemainderByZero(op.stable()) - } - AssertKind::ResumedAfterReturn(generator) => { - stable_mir::mir::AssertMessage::ResumedAfterReturn(generator.stable()) - } - AssertKind::ResumedAfterPanic(generator) => { - stable_mir::mir::AssertMessage::ResumedAfterPanic(generator.stable()) - } - AssertKind::MisalignedPointerDereference { required, found } => { - stable_mir::mir::AssertMessage::MisalignedPointerDereference { - required: required.stable(), - found: found.stable(), +impl<'tcx> Stable for mir::AssertMessage<'tcx> { + type T = stable_mir::mir::AssertMessage; + fn stable(&self) -> Self::T { + use rustc_middle::mir::AssertKind; + match self { + AssertKind::BoundsCheck { len, index } => stable_mir::mir::AssertMessage::BoundsCheck { + len: len.stable(), + index: index.stable(), + }, + AssertKind::Overflow(bin_op, op1, op2) => stable_mir::mir::AssertMessage::Overflow( + bin_op.stable(), + op1.stable(), + op2.stable(), + ), + AssertKind::OverflowNeg(op) => stable_mir::mir::AssertMessage::OverflowNeg(op.stable()), + AssertKind::DivisionByZero(op) => { + stable_mir::mir::AssertMessage::DivisionByZero(op.stable()) + } + AssertKind::RemainderByZero(op) => { + stable_mir::mir::AssertMessage::RemainderByZero(op.stable()) + } + AssertKind::ResumedAfterReturn(generator) => { + stable_mir::mir::AssertMessage::ResumedAfterReturn(generator.stable()) + } + AssertKind::ResumedAfterPanic(generator) => { + stable_mir::mir::AssertMessage::ResumedAfterPanic(generator.stable()) + } + AssertKind::MisalignedPointerDereference { required, found } => { + stable_mir::mir::AssertMessage::MisalignedPointerDereference { + required: required.stable(), + found: found.stable(), + } } } } @@ -381,7 +388,7 @@ impl<'tcx> Stable for mir::Terminator<'tcx> { Assert { cond, expected, msg, target, unwind } => Terminator::Assert { cond: cond.stable(), expected: *expected, - msg: rustc_assert_msg_to_msg(msg), + msg: msg.stable(), target: target.as_usize(), unwind: unwind.stable(), }, From 8e0a87bdf401719fa1580eb31a4d7445846f2368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 10 Jul 2023 20:22:15 +0200 Subject: [PATCH 29/50] CI: use `macos-13` runner for Apple jobs --- .github/workflows/ci.yml | 12 ++++++------ src/ci/github-actions/ci.yml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3929b064c26..0842b69c219 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -315,7 +315,7 @@ jobs: NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 - os: macos-latest + os: macos-13 - name: dist-apple-various env: SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim" @@ -326,7 +326,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-latest + os: macos-13 - name: dist-x86_64-apple-alt env: SCRIPT: "./x.py dist bootstrap --include-default-paths" @@ -337,7 +337,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-latest + os: macos-13 - name: x86_64-apple-1 env: SCRIPT: "./x.py --stage 2 test --exclude tests/ui --exclude tests/rustdoc --exclude tests/run-make-fulldeps" @@ -348,7 +348,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-latest + os: macos-13 - name: x86_64-apple-2 env: SCRIPT: "./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps" @@ -359,7 +359,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-latest + os: macos-13 - name: dist-aarch64-apple env: SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2" @@ -374,7 +374,7 @@ jobs: NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 JEMALLOC_SYS_WITH_LG_PAGE: 14 - os: macos-latest + os: macos-13 - name: x86_64-msvc env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler" diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index b5b478e60f4..55fd6cca85a 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -90,7 +90,7 @@ x--expand-yaml-anchors--remove: <<: *base-job - &job-macos-xl - os: macos-latest # We use the standard runner for now + os: macos-13 # We use the standard runner for now <<: *base-job - &job-windows-8c From b9f378b19bd5ac234139663e9df1fe8ddca5c120 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Tue, 13 Jun 2023 15:08:14 -0700 Subject: [PATCH 30/50] Implement a few more rvalue translation to smir - Introduce an Opaque type for adding information that is still internal to the compiler. --- Cargo.lock | 2 +- compiler/rustc_smir/src/lib.rs | 1 + compiler/rustc_smir/src/rustc_internal/mod.rs | 10 + compiler/rustc_smir/src/rustc_smir/mod.rs | 134 ++++++++++++- .../rustc_smir/src/stable_mir/mir/body.rs | 181 +++++++++++++++++- 5 files changed, 318 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f880fb9bafb..3b427d1f3f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4234,8 +4234,8 @@ dependencies = [ "rustc_hir", "rustc_middle", "rustc_span", - "scoped-tls", "rustc_target", + "scoped-tls", "tracing", ] diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index 21c72f3aaa1..8450bb73119 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -13,6 +13,7 @@ #![cfg_attr(not(feature = "default"), feature(rustc_private))] #![feature(local_key_cell_methods)] #![feature(ptr_metadata)] +#![feature(type_alias_impl_trait)] // Used to define opaque types. // Declare extern rustc_* crates to enable building this crate separately from the compiler. #[cfg(not(feature = "default"))] diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 609a04d263c..87e0b211556 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -3,6 +3,9 @@ //! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs //! until stable MIR is complete. +use std::fmt::Debug; +use std::string::ToString; + use crate::{ rustc_smir::Tables, stable_mir::{self, with}, @@ -49,3 +52,10 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { crate::stable_mir::run(Tables { tcx, def_ids: vec![], types: vec![] }, f); } + +/// A type that provides internal information but that can still be used for debug purpose. +pub type Opaque = impl Debug + ToString + Clone; + +pub(crate) fn opaque(value: &T) -> Opaque { + format!("{value:?}") +} diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 8a6153269a1..f22c620021e 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -7,11 +7,13 @@ //! //! For now, we are developing everything inside `rustc`, thus, we keep this module private. +use crate::rustc_internal::{self, opaque}; use crate::stable_mir::ty::{FloatTy, IntTy, RigidTy, TyKind, UintTy}; use crate::stable_mir::{self, Context}; use rustc_middle::mir; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc_target::abi::FieldIdx; use tracing::debug; impl<'tcx> Context for Tables<'tcx> { @@ -145,6 +147,13 @@ pub(crate) trait Stable { fn stable(&self) -> Self::T; } +impl Stable for DefId { + type T = stable_mir::CrateItem; + fn stable(&self) -> Self::T { + rustc_internal::crate_item(*self) + } +} + impl<'tcx> Stable for mir::Statement<'tcx> { type T = stable_mir::mir::Statement; fn stable(&self) -> Self::T { @@ -176,12 +185,18 @@ impl<'tcx> Stable for mir::Rvalue<'tcx> { match self { Use(op) => stable_mir::mir::Rvalue::Use(op.stable()), Repeat(_, _) => todo!(), - Ref(_, _, _) => todo!(), - ThreadLocalRef(_) => todo!(), - AddressOf(_, _) => todo!(), - Len(_) => todo!(), + Ref(region, kind, place) => { + stable_mir::mir::Rvalue::Ref(opaque(region), kind.stable(), place.stable()) + } + ThreadLocalRef(def_id) => stable_mir::mir::Rvalue::ThreadLocalRef(def_id.stable()), + AddressOf(mutability, place) => { + stable_mir::mir::Rvalue::AddressOf(mutability.stable(), place.stable()) + } + Len(place) => stable_mir::mir::Rvalue::Len(place.stable()), Cast(_, _, _) => todo!(), - BinaryOp(_, _) => todo!(), + BinaryOp(bin_op, ops) => { + stable_mir::mir::Rvalue::BinaryOp(bin_op.stable(), ops.0.stable(), ops.1.stable()) + } CheckedBinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::CheckedBinaryOp( bin_op.stable(), ops.0.stable(), @@ -189,14 +204,119 @@ impl<'tcx> Stable for mir::Rvalue<'tcx> { ), NullaryOp(_, _) => todo!(), UnaryOp(un_op, op) => stable_mir::mir::Rvalue::UnaryOp(un_op.stable(), op.stable()), - Discriminant(_) => todo!(), + Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable()), Aggregate(_, _) => todo!(), ShallowInitBox(_, _) => todo!(), - CopyForDeref(_) => todo!(), + CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable()), } } } +impl Stable for mir::Mutability { + type T = stable_mir::mir::Mutability; + fn stable(&self) -> Self::T { + use mir::Mutability::*; + match *self { + Not => stable_mir::mir::Mutability::Not, + Mut => stable_mir::mir::Mutability::Mut, + } + } +} + +impl Stable for mir::BorrowKind { + type T = stable_mir::mir::BorrowKind; + fn stable(&self) -> Self::T { + use mir::BorrowKind::*; + match *self { + Shared => stable_mir::mir::BorrowKind::Shared, + Shallow => stable_mir::mir::BorrowKind::Shallow, + Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable() }, + } + } +} + +impl Stable for mir::MutBorrowKind { + type T = stable_mir::mir::MutBorrowKind; + fn stable(&self) -> Self::T { + use mir::MutBorrowKind::*; + match *self { + Default => stable_mir::mir::MutBorrowKind::Default, + TwoPhaseBorrow => stable_mir::mir::MutBorrowKind::TwoPhaseBorrow, + ClosureCapture => stable_mir::mir::MutBorrowKind::ClosureCapture, + } + } +} + +impl<'tcx> Stable for mir::NullOp<'tcx> { + type T = stable_mir::mir::NullOp; + fn stable(&self) -> Self::T { + use mir::NullOp::*; + match self { + SizeOf => stable_mir::mir::NullOp::SizeOf, + AlignOf => stable_mir::mir::NullOp::AlignOf, + OffsetOf(indices) => { + stable_mir::mir::NullOp::OffsetOf(indices.iter().map(|idx| idx.stable()).collect()) + } + } + } +} + +impl Stable for mir::CastKind { + type T = stable_mir::mir::CastKind; + fn stable(&self) -> Self::T { + use mir::CastKind::*; + match self { + PointerExposeAddress => stable_mir::mir::CastKind::PointerExposeAddress, + PointerFromExposedAddress => stable_mir::mir::CastKind::PointerFromExposedAddress, + PointerCoercion(c) => stable_mir::mir::CastKind::PointerCoercion(c.stable()), + DynStar => stable_mir::mir::CastKind::DynStar, + IntToInt => stable_mir::mir::CastKind::IntToInt, + FloatToInt => stable_mir::mir::CastKind::FloatToInt, + FloatToFloat => stable_mir::mir::CastKind::FloatToFloat, + IntToFloat => stable_mir::mir::CastKind::IntToFloat, + PtrToPtr => stable_mir::mir::CastKind::PtrToPtr, + FnPtrToPtr => stable_mir::mir::CastKind::FnPtrToPtr, + Transmute => stable_mir::mir::CastKind::Transmute, + } + } +} + +impl Stable for ty::adjustment::PointerCoercion { + type T = stable_mir::mir::PointerCoercion; + fn stable(&self) -> Self::T { + use ty::adjustment::PointerCoercion; + match self { + PointerCoercion::ReifyFnPointer => stable_mir::mir::PointerCoercion::ReifyFnPointer, + PointerCoercion::UnsafeFnPointer => stable_mir::mir::PointerCoercion::UnsafeFnPointer, + PointerCoercion::ClosureFnPointer(unsafety) => { + stable_mir::mir::PointerCoercion::ClosureFnPointer(unsafety.stable()) + } + PointerCoercion::MutToConstPointer => { + stable_mir::mir::PointerCoercion::MutToConstPointer + } + PointerCoercion::ArrayToPointer => stable_mir::mir::PointerCoercion::ArrayToPointer, + PointerCoercion::Unsize => stable_mir::mir::PointerCoercion::Unsize, + } + } +} + +impl Stable for rustc_hir::Unsafety { + type T = stable_mir::mir::Safety; + fn stable(&self) -> Self::T { + match self { + rustc_hir::Unsafety::Unsafe => stable_mir::mir::Safety::Unsafe, + rustc_hir::Unsafety::Normal => stable_mir::mir::Safety::Normal, + } + } +} + +impl Stable for FieldIdx { + type T = usize; + fn stable(&self) -> Self::T { + self.as_usize() + } +} + impl<'tcx> Stable for mir::Operand<'tcx> { type T = stable_mir::mir::Operand; fn stable(&self) -> Self::T { diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs index 468e915d1a0..fa3b0d6c559 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs @@ -1,4 +1,5 @@ -use crate::stable_mir::ty::Ty; +use crate::rustc_internal::Opaque; +use crate::stable_mir::{self, ty::Ty}; #[derive(Clone, Debug)] pub struct Body { @@ -136,12 +137,98 @@ pub enum Statement { Nop, } +type Region = Opaque; + // FIXME this is incomplete #[derive(Clone, Debug)] pub enum Rvalue { - Use(Operand), + /// Creates a pointer with the indicated mutability to the place. + /// + /// This is generated by pointer casts like `&v as *const _` or raw address of expressions like + /// `&raw v` or `addr_of!(v)`. + AddressOf(Mutability, Place), + + /// * `Offset` has the same semantics as [`offset`](pointer::offset), except that the second + /// parameter may be a `usize` as well. + /// * The comparison operations accept `bool`s, `char`s, signed or unsigned integers, floats, + /// raw pointers, or function pointers and return a `bool`. The types of the operands must be + /// matching, up to the usual caveat of the lifetimes in function pointers. + /// * Left and right shift operations accept signed or unsigned integers not necessarily of the + /// same type and return a value of the same type as their LHS. Like in Rust, the RHS is + /// truncated as needed. + /// * The `Bit*` operations accept signed integers, unsigned integers, or bools with matching + /// types and return a value of that type. + /// * The remaining operations accept signed integers, unsigned integers, or floats with + /// matching types and return a value of that type. + BinaryOp(BinOp, Operand, Operand), + + /// Performs essentially all of the casts that can be performed via `as`. + /// + /// This allows for casts from/to a variety of types. + Cast(CastKind, Operand, Ty), + + /// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition. + /// + /// For addition, subtraction, and multiplication on integers the error condition is set when + /// the infinite precision result would not be equal to the actual result. CheckedBinaryOp(BinOp, Operand, Operand), + + /// A CopyForDeref is equivalent to a read from a place. + /// When such a read happens, it is guaranteed that the only use of the returned value is a + /// deref operation, immediately followed by one or more projections. + CopyForDeref(Place), + + /// Computes the discriminant of the place, returning it as an integer of type + /// [`discriminant_ty`]. Returns zero for types without discriminant. + /// + /// The validity requirements for the underlying value are undecided for this rvalue, see + /// [#91095]. Note too that the value of the discriminant is not the same thing as the + /// variant index; use [`discriminant_for_variant`] to convert. + /// + /// [`discriminant_ty`]: crate::ty::Ty::discriminant_ty + /// [#91095]: https://github.com/rust-lang/rust/issues/91095 + /// [`discriminant_for_variant`]: crate::ty::Ty::discriminant_for_variant + Discriminant(Place), + + /// Yields the length of the place, as a `usize`. + /// + /// If the type of the place is an array, this is the array length. For slices (`[T]`, not + /// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is + /// ill-formed for places of other types. + Len(Place), + + /// Creates a reference to the place. + Ref(Region, BorrowKind, Place), + + /// Transmutes a `*mut u8` into shallow-initialized `Box`. + /// + /// This is different from a normal transmute because dataflow analysis will treat the box as + /// initialized but its content as uninitialized. Like other pointer casts, this in general + /// affects alias analysis. + ShallowInitBox(Operand, Ty), + + /// Creates a pointer/reference to the given thread local. + /// + /// The yielded type is a `*mut T` if the static is mutable, otherwise if the static is extern a + /// `*const T`, and if neither of those apply a `&T`. + /// + /// **Note:** This is a runtime operation that actually executes code and is in this sense more + /// like a function call. Also, eliminating dead stores of this rvalue causes `fn main() {}` to + /// SIGILL for some reason that I (JakobDegen) never got a chance to look into. + /// + /// **Needs clarification**: Are there weird additional semantics here related to the runtime + /// nature of this operation? + ThreadLocalRef(stable_mir::CrateItem), + + /// Exactly like `BinaryOp`, but less operands. + /// + /// Also does two's-complement arithmetic. Negation requires a signed integer or a float; + /// bitwise not requires a signed integer, unsigned integer, or bool. Both operation kinds + /// return a value with the same type as their operand. UnaryOp(UnOp, Operand), + + /// Yields the operand unchanged + Use(Operand), } #[derive(Clone, Debug)] @@ -157,8 +244,98 @@ pub struct Place { pub projection: String, } +type FieldIdx = usize; + #[derive(Clone, Debug)] pub struct SwitchTarget { pub value: u128, pub target: usize, } + +#[derive(Clone, Debug)] +pub enum BorrowKind { + /// Data must be immutable and is aliasable. + Shared, + + /// The immediately borrowed place must be immutable, but projections from + /// it don't need to be. For example, a shallow borrow of `a.b` doesn't + /// conflict with a mutable borrow of `a.b.c`. + Shallow, + + /// Data is mutable and not aliasable. + Mut { + /// `true` if this borrow arose from method-call auto-ref + kind: MutBorrowKind, + }, +} + +#[derive(Clone, Debug)] +pub enum MutBorrowKind { + Default, + TwoPhaseBorrow, + ClosureCapture, +} + +#[derive(Clone, Debug)] +pub enum Mutability { + Not, + Mut, +} + +#[derive(Clone, Debug)] +pub enum Safety { + Unsafe, + Normal, +} + +#[derive(Clone, Debug)] +pub enum PointerCoercion { + /// Go from a fn-item type to a fn-pointer type. + ReifyFnPointer, + + /// Go from a safe fn pointer to an unsafe fn pointer. + UnsafeFnPointer, + + /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer. + /// It cannot convert a closure that requires unsafe. + ClosureFnPointer(Safety), + + /// Go from a mut raw pointer to a const raw pointer. + MutToConstPointer, + + /// Go from `*const [T; N]` to `*const T` + ArrayToPointer, + + /// Unsize a pointer/reference value, e.g., `&[T; n]` to + /// `&[T]`. Note that the source could be a thin or fat pointer. + /// This will do things like convert thin pointers to fat + /// pointers, or convert structs containing thin pointers to + /// structs containing fat pointers, or convert between fat + /// pointers. + Unsize, +} + +#[derive(Clone, Debug)] +pub enum CastKind { + PointerExposeAddress, + PointerFromExposedAddress, + PointerCoercion(PointerCoercion), + DynStar, + IntToInt, + FloatToInt, + FloatToFloat, + IntToFloat, + PtrToPtr, + FnPtrToPtr, + Transmute, +} + +#[derive(Clone, Debug)] +pub enum NullOp { + /// Returns the size of a value of that type. + SizeOf, + /// Returns the minimum alignment of a type. + AlignOf, + /// Returns the offset of a field. + OffsetOf(Vec), +} From 094cb1a9fbb6b2c9b6094cd6424139f70f8912cc Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 10 Jul 2023 01:45:31 -0700 Subject: [PATCH 31/50] Dynamically size sigaltstk in rustc rustc installs a signal stack that assumes that MINSIGSTKSZ is a constant, unchanging value. Newer hardware undermines that assumption greatly, with register files larger than MINSIGSTKZ. Properly handle this so that it is correct on all supported Linux versions with all CPUs. --- compiler/rustc_driver_impl/src/lib.rs | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 9352fe3147e..2e26ce111f0 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -1453,13 +1453,13 @@ mod signal_handler { /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the /// process, print a stack trace and then exit. pub(super) fn install() { + use std::alloc::{alloc, Layout}; + unsafe { - const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024; + let alt_stack_size: usize = min_sigstack_size() + 64 * 1024; let mut alt_stack: libc::stack_t = std::mem::zeroed(); - alt_stack.ss_sp = - std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap()) - as *mut libc::c_void; - alt_stack.ss_size = ALT_STACK_SIZE; + alt_stack.ss_sp = alloc(Layout::from_size_align(alt_stack_size, 1).unwrap()).cast(); + alt_stack.ss_size = alt_stack_size; libc::sigaltstack(&alt_stack, std::ptr::null_mut()); let mut sa: libc::sigaction = std::mem::zeroed(); @@ -1469,6 +1469,23 @@ mod signal_handler { libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut()); } } + + /// Modern kernels on modern hardware can have dynamic signal stack sizes. + #[cfg(any(target_os = "linux", target_os = "android"))] + fn min_sigstack_size() -> usize { + const AT_MINSIGSTKSZ: core::ffi::c_ulong = 51; + let dynamic_sigstksz = unsafe { libc::getauxval(AT_MINSIGSTKSZ) }; + // If getauxval couldn't find the entry, it returns 0, + // so take the higher of the "constant" and auxval. + // This transparently supports older kernels which don't provide AT_MINSIGSTKSZ + libc::MINSIGSTKSZ.max(dynamic_sigstksz as _) + } + + /// Not all OS support hardware where this is needed. + #[cfg(not(any(target_os = "linux", target_os = "android")))] + fn min_sigstack_size() -> usize { + libc::MINSIGSTKSZ + } } #[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))] From b706cf80b037982ba2d0d72771ae1d479a1ecfaf Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 10 Jul 2023 15:16:29 -0400 Subject: [PATCH 32/50] Update books --- src/doc/book | 2 +- src/doc/edition-guide | 2 +- src/doc/embedded-book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/doc/book b/src/doc/book index 21cf840842b..668c64760b5 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 21cf840842bdf768a798869f06373c96c1cc5122 +Subproject commit 668c64760b5c7ea654facb4ba5fe9faddfda27cc diff --git a/src/doc/edition-guide b/src/doc/edition-guide index f63e578b92f..2751bdcef12 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit f63e578b92ff43e8cc38fcaa257b660f45c8a8c2 +Subproject commit 2751bdcef125468ea2ee006c11992cd1405aebe5 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index f2aed2fe8e9..1e5556dd1b8 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit f2aed2fe8e9f55508c86ba3aa4b6789b18a08a22 +Subproject commit 1e5556dd1b864109985d5871616ae6b9164bcead diff --git a/src/doc/nomicon b/src/doc/nomicon index c369e4b4893..302b995bcb2 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit c369e4b489332f8721fbae630354fa83385d457d +Subproject commit 302b995bcb24b70fd883980fd174738c3a10b705 diff --git a/src/doc/reference b/src/doc/reference index 5ca365eac67..1ea0178266b 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 5ca365eac678cb0d41a20b3204546d6ed70c7171 +Subproject commit 1ea0178266b3f3f613b0fabdaf16a83961c99cdb diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 57636d69267..8a87926a985 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 57636d6926762861f34e030d52ca25a71e95e5bf +Subproject commit 8a87926a985ce32ca1fad1be4008ee161a0b91eb diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 17fe3e94849..b5a12d95e32 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 17fe3e948498c50e208047a750f17d6a8d89669b +Subproject commit b5a12d95e32ae53791cc6ab44417774667ed2ac6 From 8c91c8fe8455cd30954c71f0bc72d7b480c6d185 Mon Sep 17 00:00:00 2001 From: jyn Date: Mon, 10 Jul 2023 15:15:57 -0500 Subject: [PATCH 33/50] Don't print "Skipping" twice Bootstrap executes itself twice: once with DryRun::SelfCheck and DryRun::Disabled. Change it not to print the "Skipping" message if SelfCheck is enabled. See https://github.com/rust-lang/rust/actions/runs/5503931599/jobs/10029625567?pr=113514#step:24:772. --- src/bootstrap/builder.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 05b66f94727..4a7ce146e38 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -13,7 +13,7 @@ use std::process::Command; use std::time::{Duration, Instant}; use crate::cache::{Cache, Interned, INTERNER}; -use crate::config::{SplitDebuginfo, TargetSelection}; +use crate::config::{DryRun, SplitDebuginfo, TargetSelection}; use crate::doc; use crate::flags::{Color, Subcommand}; use crate::install; @@ -281,11 +281,15 @@ impl StepDescription { fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool { if builder.config.exclude.iter().any(|e| pathset.has(&e, builder.kind)) { - println!("Skipping {:?} because it is excluded", pathset); + if !matches!(builder.config.dry_run, DryRun::SelfCheck) { + println!("Skipping {:?} because it is excluded", pathset); + } return true; } - if !builder.config.exclude.is_empty() { + if !builder.config.exclude.is_empty() + && !matches!(builder.config.dry_run, DryRun::SelfCheck) + { builder.verbose(&format!( "{:?} not skipped for {:?} -- not in {:?}", pathset, self.name, builder.config.exclude From dd5fa7d9b3176f2d922bf52a34a86847adaaab4c Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 10 Jul 2023 14:53:57 -0700 Subject: [PATCH 34/50] Don't use serde-derive in the rls shim The already-small RLS shim can get a little smaller, and faster to build, if we drop the serde-derive dependency and decode the one "method" field it needs manually from `serde_json::Value`. --- Cargo.lock | 1 - src/tools/rls/Cargo.toml | 1 - src/tools/rls/src/main.rs | 9 +++++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96eda77abb2..a1bbc1dca76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3021,7 +3021,6 @@ dependencies = [ name = "rls" version = "2.0.0" dependencies = [ - "serde", "serde_json", ] diff --git a/src/tools/rls/Cargo.toml b/src/tools/rls/Cargo.toml index b84647eb332..b7aa659c25a 100644 --- a/src/tools/rls/Cargo.toml +++ b/src/tools/rls/Cargo.toml @@ -5,5 +5,4 @@ edition = "2021" license = "Apache-2.0/MIT" [dependencies] -serde = { version = "1.0.143", features = ["derive"] } serde_json = "1.0.83" diff --git a/src/tools/rls/src/main.rs b/src/tools/rls/src/main.rs index f96f1325d96..d7be108e89c 100644 --- a/src/tools/rls/src/main.rs +++ b/src/tools/rls/src/main.rs @@ -3,7 +3,7 @@ //! This is a small stub that replaces RLS to alert the user that RLS is no //! longer available. -use serde::Deserialize; +use serde_json::Value; use std::error::Error; use std::io::BufRead; use std::io::Write; @@ -21,7 +21,6 @@ fn main() { } } -#[derive(Deserialize)] struct Message { method: Option, } @@ -88,8 +87,10 @@ fn read_message_raw(reader: &mut R) -> Result fn read_message(reader: &mut R) -> Result> { let m = read_message_raw(reader)?; - match serde_json::from_str(&m) { - Ok(m) => Ok(m), + match serde_json::from_str::(&m) { + Ok(message) => Ok(Message { + method: message.get("method").and_then(|value| value.as_str().map(String::from)), + }), Err(e) => Err(format!("failed to parse message {m}\n{e}").into()), } } From dfcd3226bab5392110ab98822d4996e2b0b090dd Mon Sep 17 00:00:00 2001 From: Chris Wailes Date: Tue, 20 Jun 2023 09:47:12 -0700 Subject: [PATCH 35/50] Correct the Android stat struct definitions See https://cs.android.com/android/platform/superproject/+/master:bionic/libc/include/sys/stat.h for reference. --- library/std/src/os/android/raw.rs | 105 +++++++++++++++++------------- 1 file changed, 58 insertions(+), 47 deletions(-) diff --git a/library/std/src/os/android/raw.rs b/library/std/src/os/android/raw.rs index a255d032086..daaf3d3eac6 100644 --- a/library/std/src/os/android/raw.rs +++ b/library/std/src/os/android/raw.rs @@ -21,26 +21,26 @@ pub use self::arch::{blkcnt_t, blksize_t, dev_t, ino_t, mode_t, nlink_t, off_t, #[cfg(any(target_arch = "arm", target_arch = "x86"))] mod arch { - use crate::os::raw::{c_longlong, c_uchar, c_uint, c_ulong, c_ulonglong}; + use crate::os::raw::{c_long, c_longlong, c_uchar, c_uint, c_ulong, c_ulonglong}; use crate::os::unix::raw::{gid_t, uid_t}; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type dev_t = u64; + pub type dev_t = u32; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type mode_t = u32; + pub type mode_t = c_uint; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type blkcnt_t = u64; + pub type blkcnt_t = c_ulong; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type blksize_t = u64; + pub type blksize_t = c_ulong; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type ino_t = u64; + pub type ino_t = c_ulong; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type nlink_t = u64; + pub type nlink_t = u32; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type off_t = u64; + pub type off_t = i32; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type time_t = i64; + pub type time_t = c_long; #[repr(C)] #[derive(Clone)] @@ -70,18 +70,20 @@ mod arch { pub st_blksize: u32, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_blocks: c_ulonglong, + #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_atime: c_ulong, + pub st_atime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_atime_nsec: c_ulong, + pub st_atime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_mtime: c_ulong, + pub st_mtime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_mtime_nsec: c_ulong, + pub st_mtime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_ctime: c_ulong, + pub st_ctime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_ctime_nsec: c_ulong, + pub st_ctime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] pub st_ino: c_ulonglong, } @@ -89,26 +91,26 @@ mod arch { #[cfg(target_arch = "aarch64")] mod arch { - use crate::os::raw::{c_uchar, c_ulong}; + use crate::os::raw::{c_int, c_long, c_uint, c_ulong}; use crate::os::unix::raw::{gid_t, uid_t}; #[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = u64; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type mode_t = u32; + pub type mode_t = c_uint; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type blkcnt_t = u64; + pub type blkcnt_t = c_ulong; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type blksize_t = u64; + pub type blksize_t = c_ulong; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type ino_t = u64; + pub type ino_t = c_ulong; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type nlink_t = u64; + pub type nlink_t = u32; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type off_t = u64; + pub type off_t = i64; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type time_t = i64; + pub type time_t = c_long; #[repr(C)] #[derive(Clone)] @@ -117,9 +119,7 @@ mod arch { #[stable(feature = "raw_ext", since = "1.1.0")] pub st_dev: dev_t, #[stable(feature = "raw_ext", since = "1.1.0")] - pub __pad0: [c_uchar; 4], - #[stable(feature = "raw_ext", since = "1.1.0")] - pub __st_ino: ino_t, + pub st_ino: ino_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_mode: mode_t, #[stable(feature = "raw_ext", since = "1.1.0")] @@ -131,27 +131,33 @@ mod arch { #[stable(feature = "raw_ext", since = "1.1.0")] pub st_rdev: dev_t, #[stable(feature = "raw_ext", since = "1.1.0")] - pub __pad3: [c_uchar; 4], + pub __pad1: c_ulong, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_size: off_t, #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_blksize: blksize_t, + pub st_blksize: c_int, #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_blocks: blkcnt_t, + pub __pad2: c_int, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blocks: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] pub st_atime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_atime_nsec: c_ulong, + pub st_atime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_mtime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_mtime_nsec: c_ulong, + pub st_mtime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_ctime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_ctime_nsec: c_ulong, + pub st_ctime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_ino: ino_t, + pub __unused4: c_uint, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub __unused5: c_uint, } } @@ -163,20 +169,20 @@ mod arch { #[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = u64; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type mode_t = u32; + pub type mode_t = c_uint; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type blkcnt_t = u64; + pub type blkcnt_t = c_ulong; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type blksize_t = u64; + pub type blksize_t = c_ulong; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type ino_t = u64; + pub type ino_t = c_ulong; #[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = u32; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type off_t = u64; + pub type off_t = i64; #[stable(feature = "raw_ext", since = "1.1.0")] - pub type time_t = i64; + pub type time_t = c_long; #[repr(C)] #[derive(Clone)] @@ -195,25 +201,30 @@ mod arch { #[stable(feature = "raw_ext", since = "1.1.0")] pub st_gid: gid_t, #[stable(feature = "raw_ext", since = "1.1.0")] + pub __pad0: c_uint, + #[stable(feature = "raw_ext", since = "1.1.0")] pub st_rdev: dev_t, #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_size: i64, + pub st_size: off_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_blksize: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_blocks: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_atime: c_ulong, + pub st_atime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_atime_nsec: c_ulong, + pub st_atime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_mtime: c_ulong, + pub st_mtime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_mtime_nsec: c_ulong, + pub st_mtime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_ctime: c_ulong, + pub st_ctime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_ctime_nsec: c_ulong, - __unused: [c_long; 3], + pub st_ctime_nsec: c_long, + + #[stable(feature = "raw_ext", since = "1.1.0")] + pub __pad3: [c_long; 3], } } From b809207dec106b261884daea036fad16eb8a2f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 11 Jul 2023 01:11:21 +0200 Subject: [PATCH 36/50] Lint against misplaced where-clauses on assoc tys in traits --- .../rustc_ast_passes/src/ast_validation.rs | 31 ++++++++++--------- compiler/rustc_lint_defs/src/builtin.rs | 2 +- ...clause-placement-assoc-type-in-impl.fixed} | 0 ...re-clause-placement-assoc-type-in-impl.rs} | 0 ...lause-placement-assoc-type-in-impl.stderr} | 6 ++-- ...clause-placement-assoc-type-in-trait.fixed | 15 +++++++++ ...re-clause-placement-assoc-type-in-trait.rs | 15 +++++++++ ...lause-placement-assoc-type-in-trait.stderr | 29 +++++++++++++++++ .../where-clause-placement-type-alias.rs} | 0 .../where-clause-placement-type-alias.stderr} | 4 +-- 10 files changed, 81 insertions(+), 21 deletions(-) rename tests/ui/{parser/type-alias-where-fixable.fixed => where-clauses/where-clause-placement-assoc-type-in-impl.fixed} (100%) rename tests/ui/{parser/type-alias-where-fixable.rs => where-clauses/where-clause-placement-assoc-type-in-impl.rs} (100%) rename tests/ui/{parser/type-alias-where-fixable.stderr => where-clauses/where-clause-placement-assoc-type-in-impl.stderr} (87%) create mode 100644 tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed create mode 100644 tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs create mode 100644 tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr rename tests/ui/{parser/type-alias-where.rs => where-clauses/where-clause-placement-type-alias.rs} (100%) rename tests/ui/{parser/type-alias-where.stderr => where-clauses/where-clause-placement-type-alias.stderr} (83%) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 096cea945b0..418e1df5857 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1300,14 +1300,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }); } } - AssocItemKind::Type(box TyAlias { - generics, - where_clauses, - where_predicates_split, - bounds, - ty, - .. - }) => { + AssocItemKind::Type(box TyAlias { bounds, ty, .. }) => { if ty.is_none() { self.session.emit_err(errors::AssocTypeWithoutBody { span: item.span, @@ -1315,18 +1308,26 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }); } self.check_type_no_bounds(bounds, "`impl`s"); - if ty.is_some() { - self.check_gat_where( - item.id, - generics.where_clause.predicates.split_at(*where_predicates_split).0, - *where_clauses, - ); - } } _ => {} } } + if let AssocItemKind::Type(box TyAlias { + generics, + where_clauses, + where_predicates_split, + ty: Some(_), + .. + }) = &item.kind + { + self.check_gat_where( + item.id, + generics.where_clause.predicates.split_at(*where_predicates_split).0, + *where_clauses, + ); + } + if ctxt == AssocCtxt::Trait || self.in_trait_impl { self.visibility_not_permitted(&item.vis, errors::VisibilityNotPermittedNote::TraitImpl); if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 87c542dc2e2..a0f2e9aed81 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4084,7 +4084,7 @@ declare_lint! { /// /// ### Explanation /// - /// The preferred location for where clauses on associated types in impls + /// The preferred location for where clauses on associated types /// is after the type. However, for most of generic associated types development, /// it was only accepted before the equals. To provide a transition period and /// further evaluate this change, both are currently accepted. At some point in diff --git a/tests/ui/parser/type-alias-where-fixable.fixed b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed similarity index 100% rename from tests/ui/parser/type-alias-where-fixable.fixed rename to tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed diff --git a/tests/ui/parser/type-alias-where-fixable.rs b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs similarity index 100% rename from tests/ui/parser/type-alias-where-fixable.rs rename to tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs diff --git a/tests/ui/parser/type-alias-where-fixable.stderr b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr similarity index 87% rename from tests/ui/parser/type-alias-where-fixable.stderr rename to tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr index f0acb388b97..b4de051845f 100644 --- a/tests/ui/parser/type-alias-where-fixable.stderr +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr @@ -1,5 +1,5 @@ warning: where clause not allowed here - --> $DIR/type-alias-where-fixable.rs:13:16 + --> $DIR/where-clause-placement-assoc-type-in-impl.rs:13:16 | LL | type Assoc where u32: Copy = (); | ^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + type Assoc = () where u32: Copy; | warning: where clause not allowed here - --> $DIR/type-alias-where-fixable.rs:16:17 + --> $DIR/where-clause-placement-assoc-type-in-impl.rs:16:17 | LL | type Assoc2 where u32: Copy = () where i32: Copy; | ^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL + type Assoc2 = () where i32: Copy, u32: Copy; | warning: where clause not allowed here - --> $DIR/type-alias-where-fixable.rs:24:17 + --> $DIR/where-clause-placement-assoc-type-in-impl.rs:24:17 | LL | type Assoc2 where u32: Copy, i32: Copy = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed new file mode 100644 index 00000000000..d171eba50b7 --- /dev/null +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed @@ -0,0 +1,15 @@ +// check-pass +// run-rustfix + +#![feature(associated_type_defaults)] + +trait Trait { + // Not fine, suggests moving. + type Assoc = () where u32: Copy; + //~^ WARNING where clause not allowed here + // Not fine, suggests moving `u32: Copy` + type Assoc2 = () where i32: Copy, u32: Copy; + //~^ WARNING where clause not allowed here +} + +fn main() {} diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs new file mode 100644 index 00000000000..59afee65794 --- /dev/null +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs @@ -0,0 +1,15 @@ +// check-pass +// run-rustfix + +#![feature(associated_type_defaults)] + +trait Trait { + // Not fine, suggests moving. + type Assoc where u32: Copy = (); + //~^ WARNING where clause not allowed here + // Not fine, suggests moving `u32: Copy` + type Assoc2 where u32: Copy = () where i32: Copy; + //~^ WARNING where clause not allowed here +} + +fn main() {} diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr new file mode 100644 index 00000000000..a81cb8c8cd6 --- /dev/null +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr @@ -0,0 +1,29 @@ +warning: where clause not allowed here + --> $DIR/where-clause-placement-assoc-type-in-trait.rs:8:16 + | +LL | type Assoc where u32: Copy = (); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #89122 for more information + = note: `#[warn(deprecated_where_clause_location)]` on by default +help: move it to the end of the type declaration + | +LL - type Assoc where u32: Copy = (); +LL + type Assoc = () where u32: Copy; + | + +warning: where clause not allowed here + --> $DIR/where-clause-placement-assoc-type-in-trait.rs:11:17 + | +LL | type Assoc2 where u32: Copy = () where i32: Copy; + | ^^^^^^^^^^^^^^^ + | + = note: see issue #89122 for more information +help: move it to the end of the type declaration + | +LL - type Assoc2 where u32: Copy = () where i32: Copy; +LL + type Assoc2 = () where i32: Copy, u32: Copy; + | + +warning: 2 warnings emitted + diff --git a/tests/ui/parser/type-alias-where.rs b/tests/ui/where-clauses/where-clause-placement-type-alias.rs similarity index 100% rename from tests/ui/parser/type-alias-where.rs rename to tests/ui/where-clauses/where-clause-placement-type-alias.rs diff --git a/tests/ui/parser/type-alias-where.stderr b/tests/ui/where-clauses/where-clause-placement-type-alias.stderr similarity index 83% rename from tests/ui/parser/type-alias-where.stderr rename to tests/ui/where-clauses/where-clause-placement-type-alias.stderr index fb838179266..b3c155a48dd 100644 --- a/tests/ui/parser/type-alias-where.stderr +++ b/tests/ui/where-clauses/where-clause-placement-type-alias.stderr @@ -1,5 +1,5 @@ error: where clauses are not allowed after the type for type aliases - --> $DIR/type-alias-where.rs:6:15 + --> $DIR/where-clause-placement-type-alias.rs:6:15 | LL | type Bar = () where u32: Copy; | ^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | type Bar = () where u32: Copy; = note: see issue #89122 for more information error: where clauses are not allowed after the type for type aliases - --> $DIR/type-alias-where.rs:8:15 + --> $DIR/where-clause-placement-type-alias.rs:8:15 | LL | type Baz = () where; | ^^^^^ From 846d54f16c1048c794235fc84b05c23e72083ef6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 8 Jul 2023 05:10:24 +0000 Subject: [PATCH 37/50] Structurally resolve in pattern matching when peeling refs in new solver --- compiler/rustc_hir_typeck/src/pat.rs | 12 +++++++----- .../src/traits/error_reporting/mod.rs | 2 ++ tests/ui/panics/abort-on-panic.rs | 2 ++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 42f4531c0ef..69c8cc8c590 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -335,8 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, mut def_bm: BindingMode, ) -> (Ty<'tcx>, BindingMode) { - let mut expected = self.resolve_vars_with_obligations(expected); - + let mut expected = self.try_structurally_resolve_type(pat.span, expected); // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example, // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches // the `Some(5)` which is not of type Ref. @@ -353,7 +352,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Preserve the reference type. We'll need it later during THIR lowering. pat_adjustments.push(expected); - expected = inner_ty; + expected = self.try_structurally_resolve_type(pat.span, inner_ty); def_bm = ty::BindByReference(match def_bm { // If default binding mode is by value, make it `ref` or `ref mut` // (depending on whether we observe `&` or `&mut`). @@ -627,6 +626,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { local_ty } + /// When a variable is bound several times in a `PatKind::Or`, it'll resolve all of the + /// subsequent bindings of the same name to the first usage. Verify that all of these + /// bindings have the same type by comparing them all against the type of that first pat. fn check_binding_alt_eq_ty( &self, ba: hir::BindingAnnotation, @@ -638,7 +640,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let var_ty = self.local_ty(span, var_id); if let Some(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) { let hir = self.tcx.hir(); - let var_ty = self.resolve_vars_with_obligations(var_ty); + let var_ty = self.resolve_vars_if_possible(var_ty); let msg = format!("first introduced with type `{var_ty}` here"); err.span_label(hir.span(var_id), msg); let in_match = hir.parent_iter(var_id).any(|(_, n)| { @@ -656,7 +658,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut err, span, var_ty, - self.resolve_vars_with_obligations(ty), + self.resolve_vars_if_possible(ty), ba, ); err.emit(); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index f342180590f..4dc06d2bfac 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1640,6 +1640,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) .into(), }; + // FIXME(-Ztrait-solver=next): For diagnostic purposes, it would be nice + // to deeply normalize this type. let normalized_term = ocx.normalize(&obligation.cause, obligation.param_env, unnormalized_term); diff --git a/tests/ui/panics/abort-on-panic.rs b/tests/ui/panics/abort-on-panic.rs index 1f6ad64c071..7fbee85ffd1 100644 --- a/tests/ui/panics/abort-on-panic.rs +++ b/tests/ui/panics/abort-on-panic.rs @@ -1,4 +1,6 @@ // run-pass +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next #![allow(unused_must_use)] #![feature(c_unwind)] From b0dbd6004032287ec93f0820ce2a6fef119b89f4 Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Fri, 7 Jul 2023 02:43:04 -0700 Subject: [PATCH 38/50] optimization round 2 - moved work from `find_local` to `gather_statement` - created custom iterator for `iter_projections` - reverted change from `IndexVec` to `FxIndexMap` --- .../src/move_paths/builder.rs | 22 +++-- .../rustc_mir_dataflow/src/move_paths/mod.rs | 18 ++-- compiler/rustc_mir_dataflow/src/un_derefer.rs | 90 ++++++++++++++++--- 3 files changed, 96 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 537df1588a3..5052de99184 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -39,18 +39,18 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { locals: body .local_decls .iter_enumerated() - .filter(|(_, l)| !l.is_deref_temp()) - .map(|(i, _)| { - ( - i, + .map(|(i, l)| { + if l.is_deref_temp() { + MovePathIndex::MAX + } else { Self::new_move_path( &mut move_paths, &mut path_map, &mut init_path_map, None, Place::from(i), - ), - ) + ) + } }) .collect(), projections: Default::default(), @@ -285,8 +285,14 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { fn gather_statement(&mut self, stmt: &Statement<'tcx>) { match &stmt.kind { StatementKind::Assign(box (place, Rvalue::CopyForDeref(reffed))) => { - assert!(self.builder.body.local_decls[place.local].is_deref_temp()); - self.builder.data.rev_lookup.un_derefer.insert(place.as_local().unwrap(), *reffed); + let local = place.as_local().unwrap(); + assert!(self.builder.body.local_decls[local].is_deref_temp()); + + let rev_lookup = &mut self.builder.data.rev_lookup; + + rev_lookup.un_derefer.insert(local, reffed.as_ref()); + let base_local = rev_lookup.un_derefer.deref_chain(local).first().unwrap().local; + rev_lookup.locals[local] = rev_lookup.locals[base_local]; } StatementKind::Assign(box (place, rval)) => { self.create_move_path(*place); diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs index 0f7da4f46e3..0c7aa6676ec 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs @@ -1,6 +1,6 @@ use crate::move_paths::builder::MoveDat; use crate::un_derefer::UnDerefer; -use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; +use rustc_data_structures::fx::FxHashMap; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::*; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; @@ -291,7 +291,7 @@ impl Init { /// Tables mapping from a place to its MovePathIndex. #[derive(Debug)] pub struct MovePathLookup<'tcx> { - locals: FxIndexMap, + locals: IndexVec, /// projections are made from a base-place and a projection /// elem. The base-place will have a unique MovePathIndex; we use @@ -331,17 +331,9 @@ impl<'tcx> MovePathLookup<'tcx> { LookupResult::Exact(result) } + #[inline] pub fn find_local(&self, local: Local) -> MovePathIndex { - let deref_chain = self.un_derefer.deref_chain(local); - - let local = match deref_chain.first() { - Some(place) => place.local, - None => local, - }; - - *self.locals.get(&local).unwrap_or_else(|| { - bug!("base local ({local:?}) of deref_chain should not be a deref temp") - }) + self.locals[local] } /// An enumerated iterator of `local`s and their associated @@ -349,7 +341,7 @@ impl<'tcx> MovePathLookup<'tcx> { pub fn iter_locals_enumerated( &self, ) -> impl DoubleEndedIterator + ExactSizeIterator + '_ { - self.locals.iter().map(|(&l, &idx)| (l, idx)) + self.locals.iter_enumerated().map(|(l, &idx)| (l, idx)) } } diff --git a/compiler/rustc_mir_dataflow/src/un_derefer.rs b/compiler/rustc_mir_dataflow/src/un_derefer.rs index fdd2eb0233d..874d50ffd0e 100644 --- a/compiler/rustc_mir_dataflow/src/un_derefer.rs +++ b/compiler/rustc_mir_dataflow/src/un_derefer.rs @@ -1,36 +1,100 @@ use rustc_data_structures::fx::FxHashMap; use rustc_middle::mir::*; -use std::iter::once; - /// Used for reverting changes made by `DerefSeparator` #[derive(Default, Debug)] pub struct UnDerefer<'tcx> { - deref_chains: FxHashMap>>, + deref_chains: FxHashMap>>, } impl<'tcx> UnDerefer<'tcx> { - pub fn insert(&mut self, local: Local, reffed: Place<'tcx>) { + #[inline] + pub fn insert(&mut self, local: Local, reffed: PlaceRef<'tcx>) { let mut chain = self.deref_chains.remove(&reffed.local).unwrap_or_default(); chain.push(reffed); self.deref_chains.insert(local, chain); } /// Returns the chain of places behind `DerefTemp` locals - pub fn deref_chain(&self, local: Local) -> &[Place<'tcx>] { + #[inline] + pub fn deref_chain(&self, local: Local) -> &[PlaceRef<'tcx>] { self.deref_chains.get(&local).map(Vec::as_slice).unwrap_or_default() } + /// Iterates over the projections of a place and its deref chain. + /// + /// See [`PlaceRef::iter_projections`] + #[inline] pub fn iter_projections( &self, place: PlaceRef<'tcx>, - ) -> impl Iterator, PlaceElem<'tcx>)> + DoubleEndedIterator + '_ { - let deref_chain = self.deref_chain(place.local); - - deref_chain - .iter() - .map(Place::as_ref) - .chain(once(place)) - .flat_map(|place| place.iter_projections()) + ) -> impl Iterator, PlaceElem<'tcx>)> + '_ { + ProjectionIter::new(self.deref_chain(place.local), place) + } +} + +/// The iterator returned by [`UnDerefer::iter_projections`]. +struct ProjectionIter<'a, 'tcx> { + places: SlicePlusOne<'a, PlaceRef<'tcx>>, + proj_idx: usize, +} + +impl<'a, 'tcx> ProjectionIter<'a, 'tcx> { + #[inline] + fn new(deref_chain: &'a [PlaceRef<'tcx>], place: PlaceRef<'tcx>) -> Self { + // just return an empty iterator for a bare local + let last = if place.as_local().is_none() { + Some(place) + } else { + debug_assert!(deref_chain.is_empty()); + None + }; + + ProjectionIter { places: SlicePlusOne { slice: deref_chain, last }, proj_idx: 0 } + } +} + +impl<'tcx> Iterator for ProjectionIter<'_, 'tcx> { + type Item = (PlaceRef<'tcx>, PlaceElem<'tcx>); + + #[inline] + fn next(&mut self) -> Option<(PlaceRef<'tcx>, PlaceElem<'tcx>)> { + let place = self.places.read()?; + + // the projection should never be empty except for a bare local which is handled in new + let partial_place = + PlaceRef { local: place.local, projection: &place.projection[..self.proj_idx] }; + let elem = place.projection[self.proj_idx]; + + if self.proj_idx == place.projection.len() - 1 { + self.proj_idx = 0; + self.places.advance(); + } else { + self.proj_idx += 1; + } + + Some((partial_place, elem)) + } +} + +struct SlicePlusOne<'a, T> { + slice: &'a [T], + last: Option, +} + +impl SlicePlusOne<'_, T> { + #[inline] + fn read(&self) -> Option { + self.slice.first().copied().or(self.last) + } + + #[inline] + fn advance(&mut self) { + match self.slice { + [_, ref remainder @ ..] => { + self.slice = remainder; + } + [] => self.last = None, + } } } From e386d410e0822a038f0880e15d5241885079b011 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 11 Jul 2023 15:10:21 +0200 Subject: [PATCH 39/50] remove unnecessary `Rc` --- compiler/rustc_hir_typeck/src/lib.rs | 2 +- compiler/rustc_hir_typeck/src/method/mod.rs | 10 +++------- compiler/rustc_middle/src/ty/typeck_results.rs | 11 ++++------- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 6f82ffcfe4a..862430f5eb1 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -141,7 +141,7 @@ fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool { } fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet { - &*tcx.typeck(def_id).used_trait_imports + &tcx.typeck(def_id).used_trait_imports } fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> { diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index e52cea1889f..c59e9e315b1 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -12,7 +12,6 @@ pub use self::MethodError::*; use crate::errors::OpMethodGenericParams; use crate::FnCtxt; -use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, Diagnostic, SubdiagnosticMessage}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace}; @@ -190,11 +189,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.lint_dot_call_from_2018(self_ty, segment, span, call_expr, self_expr, &pick, args); - for import_id in &pick.import_ids { + for &import_id in &pick.import_ids { debug!("used_trait_import: {:?}", import_id); - Lrc::get_mut(&mut self.typeck_results.borrow_mut().used_trait_imports) - .unwrap() - .insert(*import_id); + self.typeck_results.borrow_mut().used_trait_imports.insert(import_id); } self.tcx.check_stability(pick.item.def_id, Some(call_expr.hir_id), span, None); @@ -567,10 +564,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!(?pick); { let mut typeck_results = self.typeck_results.borrow_mut(); - let used_trait_imports = Lrc::get_mut(&mut typeck_results.used_trait_imports).unwrap(); for import_id in pick.import_ids { debug!(used_trait_import=?import_id); - used_trait_imports.insert(import_id); + typeck_results.used_trait_imports.insert(import_id); } } diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 8cbffa14850..e85afeb4b6e 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -7,11 +7,8 @@ use crate::{ GenericArgKind, InternalSubsts, SubstsRef, Ty, UserSubsts, }, }; -use rustc_data_structures::{ - fx::{FxHashMap, FxIndexMap}, - sync::Lrc, - unord::{UnordItems, UnordSet}, -}; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; +use rustc_data_structures::unord::{UnordItems, UnordSet}; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::{ @@ -145,7 +142,7 @@ pub struct TypeckResults<'tcx> { /// This is used for warning unused imports. During type /// checking, this `Lrc` should not be cloned: it must have a ref-count /// of 1 so that we can insert things into the set mutably. - pub used_trait_imports: Lrc>, + pub used_trait_imports: UnordSet, /// If any errors occurred while type-checking this body, /// this field will be set to `Some(ErrorGuaranteed)`. @@ -273,7 +270,7 @@ impl<'tcx> TypeckResults<'tcx> { liberated_fn_sigs: Default::default(), fru_field_types: Default::default(), coercion_casts: Default::default(), - used_trait_imports: Lrc::new(Default::default()), + used_trait_imports: Default::default(), tainted_by_errors: None, concrete_opaque_types: Default::default(), closure_min_captures: Default::default(), From 9aed9697cf0c5042b0465b06071b2508e7884d2a Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 11 Jul 2023 17:14:20 +0800 Subject: [PATCH 40/50] While let suggestion will work for closure --- .../src/infer/error_reporting/suggest.rs | 81 ++++++++++--------- tests/ui/inference/issue-113354.fixed | 4 + tests/ui/inference/issue-113354.rs | 4 + tests/ui/inference/issue-113354.stderr | 14 ++++ 4 files changed, 63 insertions(+), 40 deletions(-) create mode 100644 tests/ui/inference/issue-113354.fixed create mode 100644 tests/ui/inference/issue-113354.rs create mode 100644 tests/ui/inference/issue-113354.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index 1422bdc9ea2..b0e7cf23cae 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -464,52 +464,53 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { span: Span, ) -> Option { let hir = self.tcx.hir(); - if let Some(node) = self.tcx.hir().find_by_def_id(cause.body_id) && - let hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn(_sig, _, body_id), .. - }) = node { - let body = hir.body(*body_id); + if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(cause.body_id) { + let body = hir.body(body_id); - /// Find the if expression with given span - struct IfVisitor { - pub result: bool, - pub found_if: bool, - pub err_span: Span, - } + /// Find the if expression with given span + struct IfVisitor { + pub result: bool, + pub found_if: bool, + pub err_span: Span, + } - impl<'v> Visitor<'v> for IfVisitor { - fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) { - if self.result { return; } - match ex.kind { - hir::ExprKind::If(cond, _, _) => { - self.found_if = true; - walk_expr(self, cond); - self.found_if = false; + impl<'v> Visitor<'v> for IfVisitor { + fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) { + if self.result { + return; } - _ => walk_expr(self, ex), + match ex.kind { + hir::ExprKind::If(cond, _, _) => { + self.found_if = true; + walk_expr(self, cond); + self.found_if = false; + } + _ => walk_expr(self, ex), + } + } + + fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) { + if let hir::StmtKind::Local(hir::Local { + span, pat: hir::Pat{..}, ty: None, init: Some(_), .. + }) = &ex.kind + && self.found_if + && span.eq(&self.err_span) { + self.result = true; + } + walk_stmt(self, ex); + } + + fn visit_body(&mut self, body: &'v hir::Body<'v>) { + hir::intravisit::walk_body(self, body); } } - fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) { - if let hir::StmtKind::Local(hir::Local { - span, pat: hir::Pat{..}, ty: None, init: Some(_), .. - }) = &ex.kind - && self.found_if - && span.eq(&self.err_span) { - self.result = true; - } - walk_stmt(self, ex); - } - - fn visit_body(&mut self, body: &'v hir::Body<'v>) { - hir::intravisit::walk_body(self, body); - } - } - - let mut visitor = IfVisitor { err_span: span, found_if: false, result: false }; - visitor.visit_body(&body); - if visitor.result { - return Some(TypeErrorAdditionalDiags::AddLetForLetChains{span: span.shrink_to_lo()}); + let mut visitor = IfVisitor { err_span: span, found_if: false, result: false }; + visitor.visit_body(&body); + if visitor.result { + return Some(TypeErrorAdditionalDiags::AddLetForLetChains { + span: span.shrink_to_lo(), + }); } } None diff --git a/tests/ui/inference/issue-113354.fixed b/tests/ui/inference/issue-113354.fixed new file mode 100644 index 00000000000..804db985ae1 --- /dev/null +++ b/tests/ui/inference/issue-113354.fixed @@ -0,0 +1,4 @@ +//run-rustfix +fn main() { + let _ = || { while let Some(_) = Some(1) { } }; //~ ERROR mismatched types +} diff --git a/tests/ui/inference/issue-113354.rs b/tests/ui/inference/issue-113354.rs new file mode 100644 index 00000000000..ec33d1f8b84 --- /dev/null +++ b/tests/ui/inference/issue-113354.rs @@ -0,0 +1,4 @@ +//run-rustfix +fn main() { + let _ = || { while Some(_) = Some(1) { } }; //~ ERROR mismatched types +} diff --git a/tests/ui/inference/issue-113354.stderr b/tests/ui/inference/issue-113354.stderr new file mode 100644 index 00000000000..045a5aa7bf0 --- /dev/null +++ b/tests/ui/inference/issue-113354.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-113354.rs:3:24 + | +LL | let _ = || { while Some(_) = Some(1) { } }; + | ^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | let _ = || { while let Some(_) = Some(1) { } }; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 05bc71cfaf9eb35caab425126d4fa8dcb8c62072 Mon Sep 17 00:00:00 2001 From: ekusiadadus Date: Wed, 12 Jul 2023 00:54:27 +0900 Subject: [PATCH 41/50] Revert "fix: :bug: etc/bash_complettion -> src/etc/... to avoid copy error" This reverts commit 08ce68b6a6bad360e9c3611ad60cf6598401f878. --- src/bootstrap/dist.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 4522819f996..b34a4b2dc63 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1074,11 +1074,7 @@ impl Step for Cargo { tarball.add_file(&cargo, "bin", 0o755); tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", 0o644); - tarball.add_renamed_file( - etc.join("cargo.bashcomp.sh"), - "src/etc/bash_completion.d", - "cargo", - ); + tarball.add_renamed_file(etc.join("cargo.bashcomp.sh"), "etc/bash_completion.d", "cargo"); tarball.add_dir(etc.join("man"), "share/man/man1"); tarball.add_legal_and_readme_to("share/doc/cargo"); From dd453a6a9961a5e6377add8980cf4c257ab5a395 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 10 Jul 2023 22:07:07 +0200 Subject: [PATCH 42/50] miri: protect Move() function arguments during the call --- .../src/const_eval/machine.rs | 12 +- .../src/interpret/eval_context.rs | 8 +- .../rustc_const_eval/src/interpret/intern.rs | 2 +- .../rustc_const_eval/src/interpret/machine.rs | 30 +++- .../rustc_const_eval/src/interpret/mod.rs | 1 + .../rustc_const_eval/src/interpret/operand.rs | 8 - .../rustc_const_eval/src/interpret/place.rs | 22 +-- .../src/interpret/terminator.rs | 157 ++++++++++++++---- .../rustc_const_eval/src/interpret/visitor.rs | 4 +- .../rustc_mir_transform/src/const_prop.rs | 6 +- .../src/dataflow_const_prop.rs | 4 +- src/tools/miri/src/borrow_tracker/mod.rs | 6 +- .../stacked_borrows/diagnostics.rs | 4 +- .../src/borrow_tracker/stacked_borrows/mod.rs | 32 ++-- .../src/borrow_tracker/tree_borrows/mod.rs | 33 ++-- src/tools/miri/src/lib.rs | 1 + src/tools/miri/src/machine.rs | 53 ++++-- src/tools/miri/src/shims/mod.rs | 8 +- .../fail/function_calls/arg_inplace_mutate.rs | 34 ++++ .../arg_inplace_mutate.stack.stderr | 37 +++++ .../arg_inplace_mutate.tree.stderr | 39 +++++ .../arg_inplace_observe_after.rs | 27 +++ .../arg_inplace_observe_after.stderr | 22 +++ .../arg_inplace_observe_during.none.stderr | 20 +++ .../arg_inplace_observe_during.rs | 34 ++++ .../arg_inplace_observe_during.stack.stderr | 37 +++++ .../arg_inplace_observe_during.tree.stderr | 39 +++++ .../return_pointer_aliasing.none.stderr | 20 +++ .../return_pointer_aliasing.rs | 10 +- .../return_pointer_aliasing.stack.stderr | 13 +- .../return_pointer_aliasing.tree.stderr | 13 +- .../function_calls/return_place_on_heap.rs | 25 +++ 32 files changed, 607 insertions(+), 154 deletions(-) create mode 100644 src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs create mode 100644 src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr create mode 100644 src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr create mode 100644 src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs create mode 100644 src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr create mode 100644 src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr create mode 100644 src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs create mode 100644 src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr create mode 100644 src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr create mode 100644 src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr rename src/tools/miri/tests/fail/{both_borrows => function_calls}/return_pointer_aliasing.rs (70%) rename src/tools/miri/tests/fail/{both_borrows => function_calls}/return_pointer_aliasing.stack.stderr (78%) rename src/tools/miri/tests/fail/{both_borrows => function_calls}/return_pointer_aliasing.tree.stderr (83%) create mode 100644 src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index f9f645af41f..a20f0276b3e 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -22,7 +22,7 @@ use rustc_target::spec::abi::Abi as CallAbi; use crate::errors::{LongRunning, LongRunningWarn}; use crate::interpret::{ - self, compile_time_machine, AllocId, ConstAllocation, FnVal, Frame, ImmTy, InterpCx, + self, compile_time_machine, AllocId, ConstAllocation, FnArg, FnVal, Frame, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, Scalar, }; use crate::{errors, fluent_generated as fluent}; @@ -201,7 +201,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { fn hook_special_const_fn( &mut self, instance: ty::Instance<'tcx>, - args: &[OpTy<'tcx>], + args: &[FnArg<'tcx>], dest: &PlaceTy<'tcx>, ret: Option, ) -> InterpResult<'tcx, Option>> { @@ -210,6 +210,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { if Some(def_id) == self.tcx.lang_items().panic_display() || Some(def_id) == self.tcx.lang_items().begin_panic_fn() { + let args = self.copy_fn_args(args)?; // &str or &&str assert!(args.len() == 1); @@ -236,8 +237,9 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { return Ok(Some(new_instance)); } else if Some(def_id) == self.tcx.lang_items().align_offset_fn() { + let args = self.copy_fn_args(args)?; // For align_offset, we replace the function call if the pointer has no address. - match self.align_offset(instance, args, dest, ret)? { + match self.align_offset(instance, &args, dest, ret)? { ControlFlow::Continue(()) => return Ok(Some(instance)), ControlFlow::Break(()) => return Ok(None), } @@ -293,7 +295,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { self.eval_fn_call( FnVal::Instance(instance), (CallAbi::Rust, fn_abi), - &[addr, align], + &[FnArg::Copy(addr), FnArg::Copy(align)], /* with_caller_location = */ false, dest, ret, @@ -427,7 +429,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, ecx: &mut InterpCx<'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, _abi: CallAbi, - args: &[OpTy<'tcx>], + args: &[FnArg<'tcx>], dest: &PlaceTy<'tcx>, ret: Option, _unwind: mir::UnwindAction, // unwinding is not supported in consts diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 36606ff69a6..5e5ad31d8c2 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -682,11 +682,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return_to_block: StackPopCleanup, ) -> InterpResult<'tcx> { trace!("body: {:#?}", body); - // Clobber previous return place contents, nobody is supposed to be able to see them any more - // This also checks dereferenceable, but not align. We rely on all constructed places being - // sufficiently aligned (in particular we rely on `deref_operand` checking alignment). - self.write_uninit(return_place)?; - // first push a stack frame so we have access to the local substs + // First push a stack frame so we have access to the local substs let pre_frame = Frame { body, loc: Right(body.span), // Span used for errors caused during preamble. @@ -805,6 +801,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { throw_ub_custom!(fluent::const_eval_unwind_past_top); } + M::before_stack_pop(self, self.frame())?; + // Copy return value. Must of course happen *before* we deallocate the locals. let copy_ret_result = if !unwinding { let op = self diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 7b11ad33091..107e5bec614 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -30,7 +30,7 @@ use super::{ use crate::const_eval; use crate::errors::{DanglingPtrInFinal, UnsupportedUntypedPointer}; -pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine< +pub trait CompileTimeMachine<'mir, 'tcx: 'mir, T> = Machine< 'mir, 'tcx, MemoryKind = T, diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index b448e3a24c6..e101785b6e2 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -17,7 +17,7 @@ use rustc_target::spec::abi::Abi as CallAbi; use crate::const_eval::CheckAlignment; use super::{ - AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, + AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, FnArg, Frame, ImmTy, InterpCx, InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, }; @@ -84,7 +84,7 @@ pub trait AllocMap { /// Methods of this trait signifies a point where CTFE evaluation would fail /// and some use case dependent behaviour can instead be applied. -pub trait Machine<'mir, 'tcx>: Sized { +pub trait Machine<'mir, 'tcx: 'mir>: Sized { /// Additional memory kinds a machine wishes to distinguish from the builtin ones type MemoryKind: Debug + std::fmt::Display + MayLeak + Eq + 'static; @@ -182,7 +182,7 @@ pub trait Machine<'mir, 'tcx>: Sized { ecx: &mut InterpCx<'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, abi: CallAbi, - args: &[OpTy<'tcx, Self::Provenance>], + args: &[FnArg<'tcx, Self::Provenance>], destination: &PlaceTy<'tcx, Self::Provenance>, target: Option, unwind: mir::UnwindAction, @@ -194,7 +194,7 @@ pub trait Machine<'mir, 'tcx>: Sized { ecx: &mut InterpCx<'mir, 'tcx, Self>, fn_val: Self::ExtraFnVal, abi: CallAbi, - args: &[OpTy<'tcx, Self::Provenance>], + args: &[FnArg<'tcx, Self::Provenance>], destination: &PlaceTy<'tcx, Self::Provenance>, target: Option, unwind: mir::UnwindAction, @@ -418,6 +418,18 @@ pub trait Machine<'mir, 'tcx>: Sized { Ok(()) } + /// Called on places used for in-place function argument and return value handling. + /// + /// These places need to be protected to make sure the program cannot tell whether the + /// argument/return value was actually copied or passed in-place.. + fn protect_in_place_function_argument( + ecx: &mut InterpCx<'mir, 'tcx, Self>, + place: &PlaceTy<'tcx, Self::Provenance>, + ) -> InterpResult<'tcx> { + // Without an aliasing model, all we can do is put `Uninit` into the place. + ecx.write_uninit(place) + } + /// Called immediately before a new stack frame gets pushed. fn init_frame_extra( ecx: &mut InterpCx<'mir, 'tcx, Self>, @@ -439,6 +451,14 @@ pub trait Machine<'mir, 'tcx>: Sized { Ok(()) } + /// Called just before the return value is copied to the caller-provided return place. + fn before_stack_pop( + _ecx: &InterpCx<'mir, 'tcx, Self>, + _frame: &Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>, + ) -> InterpResult<'tcx> { + Ok(()) + } + /// Called immediately after a stack frame got popped, but before jumping back to the caller. /// The `locals` have already been destroyed! fn after_stack_pop( @@ -484,7 +504,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { _ecx: &mut InterpCx<$mir, $tcx, Self>, fn_val: !, _abi: CallAbi, - _args: &[OpTy<$tcx>], + _args: &[FnArg<$tcx>], _destination: &PlaceTy<$tcx, Self::Provenance>, _target: Option, _unwind: mir::UnwindAction, diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index 898d62361ab..f657f954f9c 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -26,6 +26,7 @@ pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackP pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind}; pub use self::operand::{ImmTy, Immediate, OpTy, Operand}; pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy}; +pub use self::terminator::FnArg; pub use self::validity::{CtfeValidationMode, RefTracking}; pub use self::visitor::{MutValueVisitor, Value, ValueVisitor}; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 5f89d652fab..6727937363e 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -575,14 +575,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(op) } - /// Evaluate a bunch of operands at once - pub(super) fn eval_operands( - &self, - ops: &[mir::Operand<'tcx>], - ) -> InterpResult<'tcx, Vec>> { - ops.iter().map(|op| self.eval_operand(op, None)).collect() - } - fn eval_ty_constant( &self, val: ty::Const<'tcx>, diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index ca1106384fd..f1c777a077b 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -354,25 +354,27 @@ where #[inline] pub(super) fn get_place_alloc( &self, - place: &MPlaceTy<'tcx, M::Provenance>, + mplace: &MPlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, Option>> { - assert!(place.layout.is_sized()); - assert!(!place.meta.has_meta()); - let size = place.layout.size; - self.get_ptr_alloc(place.ptr, size, place.align) + let (size, _align) = self + .size_and_align_of_mplace(&mplace)? + .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); + // Due to packed places, only `mplace.align` matters. + self.get_ptr_alloc(mplace.ptr, size, mplace.align) } #[inline] pub(super) fn get_place_alloc_mut( &mut self, - place: &MPlaceTy<'tcx, M::Provenance>, + mplace: &MPlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, Option>> { - assert!(place.layout.is_sized()); - assert!(!place.meta.has_meta()); - let size = place.layout.size; - self.get_ptr_alloc_mut(place.ptr, size, place.align) + let (size, _align) = self + .size_and_align_of_mplace(&mplace)? + .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); + // Due to packed places, only `mplace.align` matters. + self.get_ptr_alloc_mut(mplace.ptr, size, mplace.align) } /// Check if this mplace is dereferenceable and sufficiently aligned. diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 15823a5975e..97d7a68e190 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -1,7 +1,8 @@ use std::borrow::Cow; +use either::Either; use rustc_ast::ast::InlineAsmOptions; -use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; use rustc_middle::ty::Instance; use rustc_middle::{ mir, @@ -12,12 +13,63 @@ use rustc_target::abi::call::{ArgAbi, ArgAttribute, ArgAttributes, FnAbi, PassMo use rustc_target::spec::abi::Abi; use super::{ - FnVal, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemoryKind, OpTy, Operand, - PlaceTy, Scalar, StackPopCleanup, + AllocId, FnVal, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemoryKind, OpTy, + Operand, PlaceTy, Provenance, Scalar, StackPopCleanup, }; use crate::fluent_generated as fluent; +/// An argment passed to a function. +#[derive(Clone, Debug)] +pub enum FnArg<'tcx, Prov: Provenance = AllocId> { + /// Pass a copy of the given operand. + Copy(OpTy<'tcx, Prov>), + /// Allow for the argument to be passed in-place: destroy the value originally stored at that place and + /// make the place inaccessible for the duration of the function call. + InPlace(PlaceTy<'tcx, Prov>), +} + +impl<'tcx, Prov: Provenance> FnArg<'tcx, Prov> { + pub fn layout(&self) -> &TyAndLayout<'tcx> { + match self { + FnArg::Copy(op) => &op.layout, + FnArg::InPlace(place) => &place.layout, + } + } +} + impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { + /// Make a copy of the given fn_arg. Any `InPlace` are degenerated to copies, no protection of the + /// original memory occurs. + pub fn copy_fn_arg( + &self, + arg: &FnArg<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { + match arg { + FnArg::Copy(op) => Ok(op.clone()), + FnArg::InPlace(place) => self.place_to_op(&place), + } + } + + /// Make a copy of the given fn_args. Any `InPlace` are degenerated to copies, no protection of the + /// original memory occurs. + pub fn copy_fn_args( + &self, + args: &[FnArg<'tcx, M::Provenance>], + ) -> InterpResult<'tcx, Vec>> { + args.iter().map(|fn_arg| self.copy_fn_arg(fn_arg)).collect() + } + + pub fn fn_arg_field( + &mut self, + arg: &FnArg<'tcx, M::Provenance>, + field: usize, + ) -> InterpResult<'tcx, FnArg<'tcx, M::Provenance>> { + Ok(match arg { + FnArg::Copy(op) => FnArg::Copy(self.operand_field(op, field)?), + FnArg::InPlace(place) => FnArg::InPlace(self.place_field(place, field)?), + }) + } + pub(super) fn eval_terminator( &mut self, terminator: &mir::Terminator<'tcx>, @@ -68,14 +120,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let old_stack = self.frame_idx(); let old_loc = self.frame().loc; let func = self.eval_operand(func, None)?; - let args = self.eval_operands(args)?; + let args = self.eval_fn_call_arguments(args)?; let fn_sig_binder = func.layout.ty.fn_sig(*self.tcx); let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig_binder); let extra_args = &args[fn_sig.inputs().len()..]; let extra_args = - self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout.ty)); + self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout().ty)); let (fn_val, fn_abi, with_caller_location) = match *func.layout.ty.kind() { ty::FnPtr(_sig) => { @@ -185,6 +237,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(()) } + /// Evaluate the arguments of a function call + pub(super) fn eval_fn_call_arguments( + &mut self, + ops: &[mir::Operand<'tcx>], + ) -> InterpResult<'tcx, Vec>> { + ops.iter() + .map(|op| { + Ok(match op { + mir::Operand::Move(place) => FnArg::InPlace(self.eval_place(*place)?), + _ => FnArg::Copy(self.eval_operand(op, None)?), + }) + }) + .collect() + } + fn check_argument_compat( caller_abi: &ArgAbi<'tcx, Ty<'tcx>>, callee_abi: &ArgAbi<'tcx, Ty<'tcx>>, @@ -275,7 +342,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { fn pass_argument<'x, 'y>( &mut self, caller_args: &mut impl Iterator< - Item = (&'x OpTy<'tcx, M::Provenance>, &'y ArgAbi<'tcx, Ty<'tcx>>), + Item = (&'x FnArg<'tcx, M::Provenance>, &'y ArgAbi<'tcx, Ty<'tcx>>), >, callee_abi: &ArgAbi<'tcx, Ty<'tcx>>, callee_arg: &PlaceTy<'tcx, M::Provenance>, @@ -295,21 +362,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Now, check if !Self::check_argument_compat(caller_abi, callee_abi) { let callee_ty = format!("{}", callee_arg.layout.ty); - let caller_ty = format!("{}", caller_arg.layout.ty); + let caller_ty = format!("{}", caller_arg.layout().ty); throw_ub_custom!( fluent::const_eval_incompatible_types, callee_ty = callee_ty, caller_ty = caller_ty, ) } + // We work with a copy of the argument for now; if this is in-place argument passing, we + // will later protect the source it comes from. This means the callee cannot observe if we + // did in-place of by-copy argument passing, except for pointer equality tests. + let caller_arg_copy = self.copy_fn_arg(&caller_arg)?; // Special handling for unsized parameters. - if caller_arg.layout.is_unsized() { + if caller_arg_copy.layout.is_unsized() { // `check_argument_compat` ensures that both have the same type, so we know they will use the metadata the same way. - assert_eq!(caller_arg.layout.ty, callee_arg.layout.ty); + assert_eq!(caller_arg_copy.layout.ty, callee_arg.layout.ty); // We have to properly pre-allocate the memory for the callee. - // So let's tear down some wrappers. + // So let's tear down some abstractions. // This all has to be in memory, there are no immediate unsized values. - let src = caller_arg.assert_mem_place(); + let src = caller_arg_copy.assert_mem_place(); // The destination cannot be one of these "spread args". let (dest_frame, dest_local) = callee_arg.assert_local(); // We are just initializing things, so there can't be anything here yet. @@ -331,7 +402,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // FIXME: Depending on the PassMode, this should reset some padding to uninitialized. (This // is true for all `copy_op`, but there are a lot of special cases for argument passing // specifically.) - self.copy_op(&caller_arg, callee_arg, /*allow_transmute*/ true) + self.copy_op(&caller_arg_copy, callee_arg, /*allow_transmute*/ true)?; + // If this was an in-place pass, protect the place it comes from for the duration of the call. + if let FnArg::InPlace(place) = caller_arg { + M::protect_in_place_function_argument(self, place)?; + } + Ok(()) } /// Call this function -- pushing the stack frame and initializing the arguments. @@ -346,7 +422,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &mut self, fn_val: FnVal<'tcx, M::ExtraFnVal>, (caller_abi, caller_fn_abi): (Abi, &FnAbi<'tcx, Ty<'tcx>>), - args: &[OpTy<'tcx, M::Provenance>], + args: &[FnArg<'tcx, M::Provenance>], with_caller_location: bool, destination: &PlaceTy<'tcx, M::Provenance>, target: Option, @@ -372,8 +448,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { match instance.def { ty::InstanceDef::Intrinsic(def_id) => { assert!(self.tcx.is_intrinsic(def_id)); - // caller_fn_abi is not relevant here, we interpret the arguments directly for each intrinsic. - M::call_intrinsic(self, instance, args, destination, target, unwind) + // FIXME: Should `InPlace` arguments be reset to uninit? + M::call_intrinsic( + self, + instance, + &self.copy_fn_args(args)?, + destination, + target, + unwind, + ) } ty::InstanceDef::VTableShim(..) | ty::InstanceDef::ReifyShim(..) @@ -428,7 +511,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { "caller ABI: {:?}, args: {:#?}", caller_abi, args.iter() - .map(|arg| (arg.layout.ty, format!("{:?}", **arg))) + .map(|arg| ( + arg.layout().ty, + match arg { + FnArg::Copy(op) => format!("copy({:?})", *op), + FnArg::InPlace(place) => format!("in-place({:?})", *place), + } + )) .collect::>() ); trace!( @@ -449,7 +538,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // last incoming argument. These two iterators do not have the same type, // so to keep the code paths uniform we accept an allocation // (for RustCall ABI only). - let caller_args: Cow<'_, [OpTy<'tcx, M::Provenance>]> = + let caller_args: Cow<'_, [FnArg<'tcx, M::Provenance>]> = if caller_abi == Abi::RustCall && !args.is_empty() { // Untuple let (untuple_arg, args) = args.split_last().unwrap(); @@ -458,11 +547,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { args.iter() .map(|a| Ok(a.clone())) .chain( - (0..untuple_arg.layout.fields.count()) - .map(|i| self.operand_field(untuple_arg, i)), + (0..untuple_arg.layout().fields.count()) + .map(|i| self.fn_arg_field(untuple_arg, i)), ) - .collect::>>>( - )?, + .collect::>>()?, ) } else { // Plain arg passing @@ -523,6 +611,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { caller_ty = caller_ty, ) } + // Ensure the return place is aligned and dereferenceable, and protect it for + // in-place return value passing. + if let Either::Left(mplace) = destination.as_mplace_or_local() { + self.check_mplace(mplace)?; + } else { + // Nothing to do for locals, they are always properly allocated and aligned. + } + M::protect_in_place_function_argument(self, destination)?; }; match res { Err(err) => { @@ -538,7 +634,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // We have to implement all "object safe receivers". So we have to go search for a // pointer or `dyn Trait` type, but it could be wrapped in newtypes. So recursively // unwrap those newtypes until we are there. - let mut receiver = args[0].clone(); + // An `InPlace` does nothing here, we keep the original receiver intact. We can't + // really pass the argument in-place anyway, and we are constructing a new + // `Immediate` receiver. + let mut receiver = self.copy_fn_arg(&args[0])?; let receiver_place = loop { match receiver.layout.ty.kind() { ty::Ref(..) | ty::RawPtr(..) => { @@ -648,11 +747,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } // Adjust receiver argument. Layout can be any (thin) ptr. - args[0] = ImmTy::from_immediate( - Scalar::from_maybe_pointer(adjusted_receiver, self).into(), - self.layout_of(Ty::new_mut_ptr(self.tcx.tcx, dyn_ty))?, - ) - .into(); + args[0] = FnArg::Copy( + ImmTy::from_immediate( + Scalar::from_maybe_pointer(adjusted_receiver, self).into(), + self.layout_of(Ty::new_mut_ptr(self.tcx.tcx, dyn_ty))?, + ) + .into(), + ); trace!("Patched receiver operand to {:#?}", args[0]); // recurse with concrete function self.eval_fn_call( @@ -710,7 +811,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.eval_fn_call( FnVal::Instance(instance), (Abi::Rust, fn_abi), - &[arg.into()], + &[FnArg::Copy(arg.into())], false, &ret.into(), Some(target), diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index 7a14459399c..879ae198f7e 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -13,7 +13,7 @@ use super::{InterpCx, MPlaceTy, Machine, OpTy, PlaceTy}; /// A thing that we can project into, and that has a layout. /// This wouldn't have to depend on `Machine` but with the current type inference, /// that's just more convenient to work with (avoids repeating all the `Machine` bounds). -pub trait Value<'mir, 'tcx, M: Machine<'mir, 'tcx>>: Sized { +pub trait Value<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized { /// Gets this value's layout. fn layout(&self) -> TyAndLayout<'tcx>; @@ -54,7 +54,7 @@ pub trait Value<'mir, 'tcx, M: Machine<'mir, 'tcx>>: Sized { /// A thing that we can project into given *mutable* access to `ecx`, and that has a layout. /// This wouldn't have to depend on `Machine` but with the current type inference, /// that's just more convenient to work with (avoids repeating all the `Machine` bounds). -pub trait ValueMut<'mir, 'tcx, M: Machine<'mir, 'tcx>>: Sized { +pub trait ValueMut<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized { /// Gets this value's layout. fn layout(&self) -> TyAndLayout<'tcx>; diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 2f2c7357b00..f3ac679f97b 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -22,8 +22,8 @@ use rustc_target::spec::abi::Abi as CallAbi; use crate::MirPass; use rustc_const_eval::interpret::{ - self, compile_time_machine, AllocId, ConstAllocation, ConstValue, Frame, ImmTy, Immediate, - InterpCx, InterpResult, LocalValue, MemoryKind, OpTy, PlaceTy, Pointer, Scalar, + self, compile_time_machine, AllocId, ConstAllocation, ConstValue, FnArg, Frame, ImmTy, + Immediate, InterpCx, InterpResult, LocalValue, MemoryKind, OpTy, PlaceTy, Pointer, Scalar, StackPopCleanup, }; @@ -185,7 +185,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> _ecx: &mut InterpCx<'mir, 'tcx, Self>, _instance: ty::Instance<'tcx>, _abi: CallAbi, - _args: &[OpTy<'tcx>], + _args: &[FnArg<'tcx>], _destination: &PlaceTy<'tcx>, _target: Option, _unwind: UnwindAction, diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 78fb196358f..5b6cbb5577c 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -532,7 +532,7 @@ impl<'tcx, 'map, 'a> Visitor<'tcx> for OperandCollector<'tcx, 'map, 'a> { struct DummyMachine; -impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachine { +impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachine { rustc_const_eval::interpret::compile_time_machine!(<'mir, 'tcx>); type MemoryKind = !; const PANIC_ON_ALLOC_FAIL: bool = true; @@ -557,7 +557,7 @@ impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachi _ecx: &mut InterpCx<'mir, 'tcx, Self>, _instance: ty::Instance<'tcx>, _abi: rustc_target::spec::abi::Abi, - _args: &[rustc_const_eval::interpret::OpTy<'tcx, Self::Provenance>], + _args: &[rustc_const_eval::interpret::FnArg<'tcx, Self::Provenance>], _destination: &rustc_const_eval::interpret::PlaceTy<'tcx, Self::Provenance>, _target: Option, _unwind: UnwindAction, diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index faa23fd2620..a2cf7c80950 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -302,12 +302,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - fn retag_return_place(&mut self) -> InterpResult<'tcx> { + fn protect_place(&mut self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; match method { - BorrowTrackerMethod::StackedBorrows => this.sb_retag_return_place(), - BorrowTrackerMethod::TreeBorrows => this.tb_retag_return_place(), + BorrowTrackerMethod::StackedBorrows => this.sb_protect_place(place), + BorrowTrackerMethod::TreeBorrows => this.tb_protect_place(place), } } diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs index de307a3c5f5..5ec8d80fb32 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -189,7 +189,7 @@ struct RetagOp { #[derive(Debug, Clone, Copy, PartialEq)] pub enum RetagCause { Normal, - FnReturnPlace, + InPlaceFnPassing, FnEntry, TwoPhase, } @@ -501,7 +501,7 @@ impl RetagCause { match self { RetagCause::Normal => "retag", RetagCause::FnEntry => "function-entry retag", - RetagCause::FnReturnPlace => "return-place retag", + RetagCause::InPlaceFnPassing => "in-place function argument/return passing protection", RetagCause::TwoPhase => "two-phase retag", } .to_string() diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index ca0f69450c9..e22b352e740 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -994,35 +994,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - /// After a stack frame got pushed, retag the return place so that we are sure - /// it does not alias with anything. - /// - /// This is a HACK because there is nothing in MIR that would make the retag - /// explicit. Also see . - fn sb_retag_return_place(&mut self) -> InterpResult<'tcx> { + /// Protect a place so that it cannot be used any more for the duration of the current function + /// call. + /// + /// This is used to ensure soundness of in-place function argument/return passing. + fn sb_protect_place(&mut self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let return_place = &this.frame().return_place; - if return_place.layout.is_zst() { - // There may not be any memory here, nothing to do. - return Ok(()); - } - // We need this to be in-memory to use tagged pointers. - let return_place = this.force_allocation(&return_place.clone())?; - // We have to turn the place into a pointer to use the existing code. + // We have to turn the place into a pointer to use the usual retagging logic. // (The pointer type does not matter, so we use a raw pointer.) - let ptr_layout = this.layout_of(Ty::new_mut_ptr(this.tcx.tcx, return_place.layout.ty))?; - let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout); - // Reborrow it. With protection! That is part of the point. + let ptr_layout = this.layout_of(Ty::new_mut_ptr(this.tcx.tcx, place.layout.ty))?; + let ptr = ImmTy::from_immediate(place.to_ref(this), ptr_layout); + // Reborrow it. With protection! That is the entire point. let new_perm = NewPermission::Uniform { perm: Permission::Unique, access: Some(AccessKind::Write), protector: Some(ProtectorKind::StrongProtector), }; - let val = this.sb_retag_reference(&val, new_perm, RetagCause::FnReturnPlace)?; - // And use reborrowed pointer for return place. - let return_place = this.ref_to_mplace(&val)?; - this.frame_mut().return_place = return_place.into(); + let _new_ptr = this.sb_retag_reference(&ptr, new_perm, RetagCause::InPlaceFnPassing)?; + // We just throw away `new_ptr`, so nobody can access this memory while it is protected. Ok(()) } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 3bb38a249ff..a3f0310f1df 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -493,36 +493,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - /// After a stack frame got pushed, retag the return place so that we are sure - /// it does not alias with anything. - /// - /// This is a HACK because there is nothing in MIR that would make the retag - /// explicit. Also see . - fn tb_retag_return_place(&mut self) -> InterpResult<'tcx> { + /// Protect a place so that it cannot be used any more for the duration of the current function + /// call. + /// + /// This is used to ensure soundness of in-place function argument/return passing. + fn tb_protect_place(&mut self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - //this.debug_hint_location(); - let return_place = &this.frame().return_place; - if return_place.layout.is_zst() { - // There may not be any memory here, nothing to do. - return Ok(()); - } - // We need this to be in-memory to use tagged pointers. - let return_place = this.force_allocation(&return_place.clone())?; - // We have to turn the place into a pointer to use the existing code. + // We have to turn the place into a pointer to use the usual retagging logic. // (The pointer type does not matter, so we use a raw pointer.) - let ptr_layout = this.layout_of(Ty::new_mut_ptr(this.tcx.tcx, return_place.layout.ty))?; - let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout); - // Reborrow it. With protection! That is part of the point. + let ptr_layout = this.layout_of(Ty::new_mut_ptr(this.tcx.tcx, place.layout.ty))?; + let ptr = ImmTy::from_immediate(place.to_ref(this), ptr_layout); + // Reborrow it. With protection! That is the entire point. let new_perm = Some(NewPermission { initial_state: Permission::new_active(), zero_size: false, protector: Some(ProtectorKind::StrongProtector), }); - let val = this.tb_retag_reference(&val, new_perm)?; - // And use reborrowed pointer for return place. - let return_place = this.ref_to_mplace(&val)?; - this.frame_mut().return_place = return_place.into(); + let _new_ptr = this.tb_retag_reference(&ptr, new_perm)?; + // We just throw away `new_ptr`, so nobody can access this memory while it is protected. Ok(()) } diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 7e92dc7a0c7..4a093d7bcc6 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -55,6 +55,7 @@ extern crate rustc_index; extern crate rustc_session; extern crate rustc_span; extern crate rustc_target; +extern crate either; // the one from rustc // Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta // files. diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index ac2bad22119..5510e3f94b7 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -7,6 +7,7 @@ use std::fmt; use std::path::Path; use std::process; +use either::Either; use rand::rngs::StdRng; use rand::SeedableRng; @@ -533,7 +534,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { let target = &tcx.sess.target; match target.arch.as_ref() { "wasm32" | "wasm64" => 64 * 1024, // https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances - "aarch64" => + "aarch64" => { if target.options.vendor.as_ref() == "apple" { // No "definitive" source, but see: // https://www.wwdcnotes.com/notes/wwdc20/10214/ @@ -541,7 +542,8 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { 16 * 1024 } else { 4 * 1024 - }, + } + } _ => 4 * 1024, } }; @@ -892,7 +894,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ecx: &mut MiriInterpCx<'mir, 'tcx>, instance: ty::Instance<'tcx>, abi: Abi, - args: &[OpTy<'tcx, Provenance>], + args: &[FnArg<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, ret: Option, unwind: mir::UnwindAction, @@ -905,12 +907,13 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ecx: &mut MiriInterpCx<'mir, 'tcx>, fn_val: Dlsym, abi: Abi, - args: &[OpTy<'tcx, Provenance>], + args: &[FnArg<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, ret: Option, _unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { - ecx.call_dlsym(fn_val, abi, args, dest, ret) + let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit? + ecx.call_dlsym(fn_val, abi, &args, dest, ret) } #[inline(always)] @@ -1094,8 +1097,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ptr: Pointer, ) -> InterpResult<'tcx> { match ptr.provenance { - Provenance::Concrete { alloc_id, tag } => - intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag), + Provenance::Concrete { alloc_id, tag } => { + intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag) + } Provenance::Wildcard => { // No need to do anything for wildcard pointers as // their provenances have already been previously exposed. @@ -1206,6 +1210,25 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { Ok(()) } + fn protect_in_place_function_argument( + ecx: &mut InterpCx<'mir, 'tcx, Self>, + place: &PlaceTy<'tcx, Provenance>, + ) -> InterpResult<'tcx> { + // We do need to write `uninit` so that even after the call ends, the former contents of + // this place cannot be observed any more. + ecx.write_uninit(place)?; + // If we have a borrow tracker, we also have it set up protection so that all reads *and + // writes* during this call are insta-UB. + if ecx.machine.borrow_tracker.is_some() { + if let Either::Left(place) = place.as_mplace_or_local() { + ecx.protect_place(&place)?; + } else { + // Locals that don't have their address taken are as protected as they can ever be. + } + } + Ok(()) + } + #[inline(always)] fn init_frame_extra( ecx: &mut InterpCx<'mir, 'tcx, Self>, @@ -1288,8 +1311,17 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { let stack_len = ecx.active_thread_stack().len(); ecx.active_thread_mut().set_top_user_relevant_frame(stack_len - 1); } - if ecx.machine.borrow_tracker.is_some() { - ecx.retag_return_place()?; + Ok(()) + } + + fn before_stack_pop( + ecx: &InterpCx<'mir, 'tcx, Self>, + frame: &Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>, + ) -> InterpResult<'tcx> { + // We want this *before* the return value copy, because the return place itself is protected + // until we do `end_call` here. + if let Some(borrow_tracker) = &ecx.machine.borrow_tracker { + borrow_tracker.borrow_mut().end_call(&frame.extra); } Ok(()) } @@ -1308,9 +1340,6 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ecx.active_thread_mut().recompute_top_user_relevant_frame(); } let timing = frame.extra.timing.take(); - if let Some(borrow_tracker) = &ecx.machine.borrow_tracker { - borrow_tracker.borrow_mut().end_call(&frame.extra); - } let res = ecx.handle_stack_pop_unwind(frame.extra, unwinding); if let Some(profiler) = ecx.machine.profiler.as_ref() { profiler.finish_recording_interval_event(timing.unwrap()); diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index a423a0786b7..1027b24e301 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -31,7 +31,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &mut self, instance: ty::Instance<'tcx>, abi: Abi, - args: &[OpTy<'tcx, Provenance>], + args: &[FnArg<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, ret: Option, unwind: mir::UnwindAction, @@ -41,7 +41,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // There are some more lang items we want to hook that CTFE does not hook (yet). if this.tcx.lang_items().align_offset_fn() == Some(instance.def.def_id()) { - let [ptr, align] = check_arg_count(args)?; + let args = this.copy_fn_args(args)?; + let [ptr, align] = check_arg_count(&args)?; if this.align_offset(ptr, align, dest, ret, unwind)? { return Ok(None); } @@ -55,7 +56,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // to run extra MIR), and Ok(Some(body)) if we found MIR to run for the // foreign function // Any needed call to `goto_block` will be performed by `emulate_foreign_item`. - return this.emulate_foreign_item(instance.def_id(), abi, args, dest, ret, unwind); + let args = this.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit? + return this.emulate_foreign_item(instance.def_id(), abi, &args, dest, ret, unwind); } // Otherwise, load the MIR. diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs new file mode 100644 index 00000000000..625a8bda8af --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs @@ -0,0 +1,34 @@ +//@revisions: stack tree +//@[tree]compile-flags: -Zmiri-tree-borrows +#![feature(custom_mir, core_intrinsics)] +use std::intrinsics::mir::*; + +pub struct S(i32); + +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn main() { + mir! { + let unit: (); + { + let non_copy = S(42); + let ptr = std::ptr::addr_of_mut!(non_copy); + // Inside `callee`, the first argument and `*ptr` are basically + // aliasing places! + Call(unit, after_call, callee(Move(*ptr), ptr)) + } + after_call = { + Return() + } + + } +} + +pub fn callee(x: S, ptr: *mut S) { + // With the setup above, if `x` is indeed moved in + // (i.e. we actually just get a pointer to the underlying storage), + // then writing to `ptr` will change the value stored in `x`! + unsafe { ptr.write(S(0)) }; + //~[stack]^ ERROR: not granting access + //~[tree]| ERROR: /write access .* forbidden/ + assert_eq!(x.0, 42); +} diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr new file mode 100644 index 00000000000..471dc1dd6dd --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr @@ -0,0 +1,37 @@ +error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID + --> $DIR/arg_inplace_mutate.rs:LL:CC + | +LL | unsafe { ptr.write(S(0)) }; + | ^^^^^^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information +help: was created by a SharedReadWrite retag at offsets [0x0..0x4] + --> $DIR/arg_inplace_mutate.rs:LL:CC + | +LL | / mir! { +LL | | let unit: (); +LL | | { +LL | | let non_copy = S(42); +... | +LL | | +LL | | } + | |_____^ +help: is this argument + --> $DIR/arg_inplace_mutate.rs:LL:CC + | +LL | unsafe { ptr.write(S(0)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: BACKTRACE (of the first span): + = note: inside `callee` at $DIR/arg_inplace_mutate.rs:LL:CC +note: inside `main` + --> $DIR/arg_inplace_mutate.rs:LL:CC + | +LL | Call(unit, after_call, callee(Move(*ptr), ptr)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr new file mode 100644 index 00000000000..35c02cc2ebd --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr @@ -0,0 +1,39 @@ +error: Undefined Behavior: write access through (root of the allocation) is forbidden + --> $DIR/arg_inplace_mutate.rs:LL:CC + | +LL | unsafe { ptr.write(S(0)) }; + | ^^^^^^^^^^^^^^^ write access through (root of the allocation) is forbidden + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: the accessed tag (root of the allocation) is foreign to the protected tag (i.e., it is not a child) + = help: this foreign write access would cause the protected tag to transition from Active to Disabled + = help: this transition would be a loss of read and write permissions, which is not allowed for protected tags +help: the accessed tag was created here + --> $DIR/arg_inplace_mutate.rs:LL:CC + | +LL | / mir! { +LL | | let unit: (); +LL | | { +LL | | let non_copy = S(42); +... | +LL | | +LL | | } + | |_____^ +help: the protected tag was created here, in the initial state Active + --> $DIR/arg_inplace_mutate.rs:LL:CC + | +LL | unsafe { ptr.write(S(0)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: BACKTRACE (of the first span): + = note: inside `callee` at $DIR/arg_inplace_mutate.rs:LL:CC +note: inside `main` + --> $DIR/arg_inplace_mutate.rs:LL:CC + | +LL | Call(unit, after_call, callee(Move(*ptr), ptr)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs new file mode 100644 index 00000000000..8eda913feb4 --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs @@ -0,0 +1,27 @@ +#![feature(custom_mir, core_intrinsics)] +use std::intrinsics::mir::*; + +pub struct S(i32); + +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn main() { + // FIXME: the span is not great (probably caused by custom MIR) + mir! { //~ERROR: uninitialized + let unit: (); + { + let non_copy = S(42); + // This could change `non_copy` in-place + Call(unit, after_call, change_arg(Move(non_copy))) + } + after_call = { + // So now we must not be allowed to observe non-copy again. + let _observe = non_copy.0; + Return() + } + + } +} + +pub fn change_arg(mut x: S) { + x.0 = 0; +} diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr new file mode 100644 index 00000000000..3ff7976c70b --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr @@ -0,0 +1,22 @@ +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/arg_inplace_observe_after.rs:LL:CC + | +LL | / mir! { +LL | | let unit: (); +LL | | { +LL | | let non_copy = S(42); +... | +LL | | +LL | | } + | |_____^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at RUSTLIB/core/src/intrinsics/mir.rs:LL:CC + = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr new file mode 100644 index 00000000000..baa91484793 --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/arg_inplace_observe_during.rs:LL:CC + | +LL | unsafe { ptr.read() }; + | ^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `change_arg` at $DIR/arg_inplace_observe_during.rs:LL:CC +note: inside `main` + --> $DIR/arg_inplace_observe_during.rs:LL:CC + | +LL | Call(unit, after_call, change_arg(Move(*ptr), ptr)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs new file mode 100644 index 00000000000..2e57872db96 --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs @@ -0,0 +1,34 @@ +//@revisions: stack tree none +//@[tree]compile-flags: -Zmiri-tree-borrows +//@[none]compile-flags: -Zmiri-disable-stacked-borrows +#![feature(custom_mir, core_intrinsics)] +use std::intrinsics::mir::*; + +pub struct S(i32); + +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn main() { + mir! { + let unit: (); + { + let non_copy = S(42); + let ptr = std::ptr::addr_of_mut!(non_copy); + // This could change `non_copy` in-place + Call(unit, after_call, change_arg(Move(*ptr), ptr)) + } + after_call = { + Return() + } + + } +} + +pub fn change_arg(mut x: S, ptr: *mut S) { + x.0 = 0; + // If `x` got passed in-place, we'd see the write through `ptr`! + // Make sure we are not allowed to do that read. + unsafe { ptr.read() }; + //~[stack]^ ERROR: not granting access + //~[tree]| ERROR: /read access .* forbidden/ + //~[none]| ERROR: uninitialized +} diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr new file mode 100644 index 00000000000..a842d3a8044 --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr @@ -0,0 +1,37 @@ +error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID + --> $DIR/arg_inplace_observe_during.rs:LL:CC + | +LL | unsafe { ptr.read() }; + | ^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information +help: was created by a SharedReadWrite retag at offsets [0x0..0x4] + --> $DIR/arg_inplace_observe_during.rs:LL:CC + | +LL | / mir! { +LL | | let unit: (); +LL | | { +LL | | let non_copy = S(42); +... | +LL | | +LL | | } + | |_____^ +help: is this argument + --> $DIR/arg_inplace_observe_during.rs:LL:CC + | +LL | x.0 = 0; + | ^^^^^^^ + = note: BACKTRACE (of the first span): + = note: inside `change_arg` at $DIR/arg_inplace_observe_during.rs:LL:CC +note: inside `main` + --> $DIR/arg_inplace_observe_during.rs:LL:CC + | +LL | Call(unit, after_call, change_arg(Move(*ptr), ptr)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr new file mode 100644 index 00000000000..cbd76c38f62 --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr @@ -0,0 +1,39 @@ +error: Undefined Behavior: read access through (root of the allocation) is forbidden + --> $DIR/arg_inplace_observe_during.rs:LL:CC + | +LL | unsafe { ptr.read() }; + | ^^^^^^^^^^ read access through (root of the allocation) is forbidden + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: the accessed tag (root of the allocation) is foreign to the protected tag (i.e., it is not a child) + = help: this foreign read access would cause the protected tag to transition from Active to Frozen + = help: this transition would be a loss of write permissions, which is not allowed for protected tags +help: the accessed tag was created here + --> $DIR/arg_inplace_observe_during.rs:LL:CC + | +LL | / mir! { +LL | | let unit: (); +LL | | { +LL | | let non_copy = S(42); +... | +LL | | +LL | | } + | |_____^ +help: the protected tag was created here, in the initial state Active + --> $DIR/arg_inplace_observe_during.rs:LL:CC + | +LL | x.0 = 0; + | ^^^^^^^ + = note: BACKTRACE (of the first span): + = note: inside `change_arg` at $DIR/arg_inplace_observe_during.rs:LL:CC +note: inside `main` + --> $DIR/arg_inplace_observe_during.rs:LL:CC + | +LL | Call(unit, after_call, change_arg(Move(*ptr), ptr)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr new file mode 100644 index 00000000000..9d9dfc89f89 --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/return_pointer_aliasing.rs:LL:CC + | +LL | unsafe { ptr.read() }; + | ^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `myfun` at $DIR/return_pointer_aliasing.rs:LL:CC +note: inside `main` + --> $DIR/return_pointer_aliasing.rs:LL:CC + | +LL | Call(*ptr, after_call, myfun(ptr)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs similarity index 70% rename from src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.rs rename to src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs index 03886e7874d..829809102fa 100644 --- a/src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.rs +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs @@ -1,11 +1,11 @@ -//@revisions: stack tree +//@revisions: stack tree none //@[tree]compile-flags: -Zmiri-tree-borrows +//@[none]compile-flags: -Zmiri-disable-stacked-borrows #![feature(raw_ref_op)] #![feature(core_intrinsics)] #![feature(custom_mir)] use std::intrinsics::mir::*; -use std::mem::MaybeUninit; #[custom_mir(dialect = "runtime", phase = "optimized")] pub fn main() { @@ -25,8 +25,10 @@ pub fn main() { } fn myfun(ptr: *mut i32) -> i32 { - unsafe { ptr.cast::>().read() }; - //~[stack]^ ERROR: /not granting access/ + unsafe { ptr.read() }; + //~[stack]^ ERROR: not granting access //~[tree]| ERROR: /read access .* forbidden/ + //~[none]| ERROR: uninitialized + // Without an aliasing model, reads are "fine" but at least they return uninit data. 13 } diff --git a/src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr similarity index 78% rename from src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.stack.stderr rename to src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr index 5bdddf5e49c..d486dcb95df 100644 --- a/src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID --> $DIR/return_pointer_aliasing.rs:LL:CC | -LL | unsafe { ptr.cast::>().read() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID +LL | unsafe { ptr.read() }; + | ^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information @@ -20,13 +20,8 @@ LL | | } help: is this argument --> $DIR/return_pointer_aliasing.rs:LL:CC | -LL | / fn myfun(ptr: *mut i32) -> i32 { -LL | | unsafe { ptr.cast::>().read() }; -LL | | -LL | | -LL | | 13 -LL | | } - | |_^ +LL | unsafe { ptr.read() }; + | ^^^^^^^^^^^^^^^^^^^^^ = note: BACKTRACE (of the first span): = note: inside `myfun` at $DIR/return_pointer_aliasing.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr similarity index 83% rename from src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.tree.stderr rename to src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr index dd76d65c7ca..c2c9de3f4ee 100644 --- a/src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: read access through (root of the allocation) is forbidden --> $DIR/return_pointer_aliasing.rs:LL:CC | -LL | unsafe { ptr.cast::>().read() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ read access through (root of the allocation) is forbidden +LL | unsafe { ptr.read() }; + | ^^^^^^^^^^ read access through (root of the allocation) is forbidden | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental = help: the accessed tag (root of the allocation) is foreign to the protected tag (i.e., it is not a child) @@ -22,13 +22,8 @@ LL | | } help: the protected tag was created here, in the initial state Active --> $DIR/return_pointer_aliasing.rs:LL:CC | -LL | / fn myfun(ptr: *mut i32) -> i32 { -LL | | unsafe { ptr.cast::>().read() }; -LL | | -LL | | -LL | | 13 -LL | | } - | |_^ +LL | unsafe { ptr.read() }; + | ^^^^^^^^^^^^^^^^^^^^^ = note: BACKTRACE (of the first span): = note: inside `myfun` at $DIR/return_pointer_aliasing.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs new file mode 100644 index 00000000000..dcfebd0f82b --- /dev/null +++ b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs @@ -0,0 +1,25 @@ +#![feature(raw_ref_op)] +#![feature(core_intrinsics)] +#![feature(custom_mir)] + +use std::intrinsics::mir::*; + +// Make sure calls with the return place "on the heap" work. +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn main() { + mir! { + { + let x = 0; + let ptr = &raw mut x; + Call(*ptr, after_call, myfun()) + } + + after_call = { + Return() + } + } +} + +fn myfun() -> i32 { + 13 +} From 95392ef0c92dabdb2baf7b91f7f50e9866444275 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 10 Jul 2023 22:14:28 +0200 Subject: [PATCH 43/50] miri tree borrows: skip retag_reference early if there is no NewPermission --- .../src/borrow_tracker/tree_borrows/mod.rs | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index a3f0310f1df..274a4a0aaba 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -178,7 +178,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' &mut self, place: &MPlaceTy<'tcx, Provenance>, // parent tag extracted from here ptr_size: Size, - new_perm: Option, + new_perm: NewPermission, new_tag: BorTag, ) -> InterpResult<'tcx, Option<(AllocId, BorTag)>> { let this = self.eval_context_mut(); @@ -256,10 +256,6 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' ptr_size.bytes() ); - let Some(new_perm) = new_perm else { - return Ok(Some((alloc_id, orig_tag))); - }; - if let Some(protect) = new_perm.protector { // We register the protection in two different places. // This makes creating a protector slower, but checking whether a tag @@ -305,7 +301,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' fn tb_retag_reference( &mut self, val: &ImmTy<'tcx, Provenance>, - new_perm: Option, + new_perm: NewPermission, ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { let this = self.eval_context_mut(); // We want a place for where the ptr *points to*, so we get one. @@ -317,7 +313,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' // - if the pointer is not reborrowed (raw pointer) or if `zero_size` is set // then we override the size to do a zero-length reborrow. let reborrow_size = match new_perm { - Some(NewPermission { zero_size: false, .. }) => + NewPermission { zero_size: false, .. } => this.size_and_align_of_mplace(&place)? .map(|(size, _)| size) .unwrap_or(place.layout.size), @@ -374,7 +370,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { NewPermission::from_ref_ty(pointee, mutability, kind, this), _ => None, }; - this.tb_retag_reference(val, new_perm) + if let Some(new_perm) = new_perm { + this.tb_retag_reference(val, new_perm) + } else { + Ok(val.clone()) + } } /// Retag all pointers that are stored in this place. @@ -405,9 +405,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { place: &PlaceTy<'tcx, Provenance>, new_perm: Option, ) -> InterpResult<'tcx> { - let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?; - let val = self.ecx.tb_retag_reference(&val, new_perm)?; - self.ecx.write_immediate(*val, place)?; + if let Some(new_perm) = new_perm { + let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?; + let val = self.ecx.tb_retag_reference(&val, new_perm)?; + self.ecx.write_immediate(*val, place)?; + } Ok(()) } } @@ -505,11 +507,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let ptr_layout = this.layout_of(Ty::new_mut_ptr(this.tcx.tcx, place.layout.ty))?; let ptr = ImmTy::from_immediate(place.to_ref(this), ptr_layout); // Reborrow it. With protection! That is the entire point. - let new_perm = Some(NewPermission { + let new_perm = NewPermission { initial_state: Permission::new_active(), zero_size: false, protector: Some(ProtectorKind::StrongProtector), - }); + }; let _new_ptr = this.tb_retag_reference(&ptr, new_perm)?; // We just throw away `new_ptr`, so nobody can access this memory while it is protected. From 124fb1490a7894fbaa319e92d59b79817a407d44 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 10 Jul 2023 22:25:53 +0200 Subject: [PATCH 44/50] update Operand::Move docs --- compiler/rustc_middle/src/mir/syntax.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 7f1d3820341..8c8efc36a2f 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1050,10 +1050,6 @@ pub type PlaceElem<'tcx> = ProjectionElem>; /// there may be other effects: if the type has a validity constraint loading the place might be UB /// if the validity constraint is not met. /// -/// **Needs clarification:** Ralf proposes that loading a place not have side-effects. -/// This is what is implemented in miri today. Are these the semantics we want for MIR? Is this -/// something we can even decide without knowing more about Rust's memory model? -/// /// **Needs clarification:** Is loading a place that has its variant index set well-formed? Miri /// currently implements it, but it seems like this may be something to check against in the /// validator. @@ -1071,6 +1067,16 @@ pub enum Operand<'tcx> { /// in [UCG#188]. You should not emit MIR that may attempt a subsequent second load of this /// place without first re-initializing it. /// + /// **Needs clarification:** The operational impact of `Move` is unclear. Currently (both in + /// Miri and codegen) it has no effect at all unless it appears in an argument to `Call`; for + /// `Call` it allows the argument to be passed to the callee "in-place", i.e. the callee might + /// just get a reference to this place instead of a full copy. Miri implements this with a + /// combination of aliasing model "protectors" and putting `uninit` into the place. Ralf + /// proposes that we don't want these semantics for `Move` in regular assignments, because + /// loading a place should not have side-effects, and the aliasing model "protectors" are + /// inherently tied to a function call. Are these the semantics we want for MIR? Is this + /// something we can even decide without knowing more about Rust's memory model? + /// /// [UCG#188]: https://github.com/rust-lang/unsafe-code-guidelines/issues/188 Move(Place<'tcx>), From e7c6db7d44b8627b9b3b1106fc08413c52fbabaa Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 11 Jul 2023 15:50:11 +0200 Subject: [PATCH 45/50] fix handling of alignment for dyn-sized places --- compiler/rustc_const_eval/src/interpret/place.rs | 10 ++++++---- .../tests/fail/unaligned_pointers/dyn_alignment.rs | 7 ++++--- .../tests/fail/unaligned_pointers/dyn_alignment.stderr | 4 ++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index f1c777a077b..c2fb61753fe 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -328,7 +328,8 @@ where }; let mplace = MemPlace { ptr: ptr.to_pointer(self)?, meta }; - // When deref'ing a pointer, the *static* alignment given by the type is what matters. + // `ref_to_mplace` is called on raw pointers even if they don't actually get dereferenced; + // we hence can't call `size_and_align_of` since that asserts more validity than we want. let align = layout.align.abi; Ok(MPlaceTy { mplace, layout, align }) } @@ -379,11 +380,12 @@ where /// Check if this mplace is dereferenceable and sufficiently aligned. pub fn check_mplace(&self, mplace: MPlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> { - let (size, align) = self + let (size, _align) = self .size_and_align_of_mplace(&mplace)? .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); - assert!(mplace.align <= align, "dynamic alignment less strict than static one?"); - let align = if M::enforce_alignment(self).should_check() { align } else { Align::ONE }; + // Due to packed places, only `mplace.align` matters. + let align = + if M::enforce_alignment(self).should_check() { mplace.align } else { Align::ONE }; self.check_ptr_access_align(mplace.ptr, size, align, CheckInAllocMsg::DerefTest)?; Ok(()) } diff --git a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs index 6d31ded75c6..555aa57de30 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs +++ b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs @@ -1,5 +1,6 @@ -// should find the bug even without validation and stacked borrows, but gets masked by optimizations -//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Zmir-opt-level=0 -Cdebug-assertions=no +// should find the bug even without, but gets masked by optimizations +//@compile-flags: -Zmiri-disable-stacked-borrows -Zmir-opt-level=0 -Cdebug-assertions=no +//@normalize-stderr-test: "but found [0-9]+" -> "but found $$ALIGN" #[repr(align(256))] #[derive(Debug)] @@ -19,6 +20,6 @@ fn main() { (&mut ptr as *mut _ as *mut *const u8).write(&buf as *const _ as *const u8); } // Re-borrow that. This should be UB. - let _ptr = &*ptr; //~ERROR: alignment 256 is required + let _ptr = &*ptr; //~ERROR: required 256 byte alignment } } diff --git a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr index a900b46612b..503721b9551 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: accessing memory with alignment ALIGN, but alignment ALIGN is required +error: Undefined Behavior: constructing invalid value: encountered an unaligned reference (required 256 byte alignment but found $ALIGN) --> $DIR/dyn_alignment.rs:LL:CC | LL | let _ptr = &*ptr; - | ^^^^^ accessing memory with alignment ALIGN, but alignment ALIGN is required + | ^^^^^ constructing invalid value: encountered an unaligned reference (required 256 byte alignment but found $ALIGN) | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information From 650243977beb19a9e168626e3421578c000d21d9 Mon Sep 17 00:00:00 2001 From: Charisee Date: Tue, 11 Jul 2023 23:48:18 +0000 Subject: [PATCH 46/50] Use constants from object crate Replace hard-coded values with GNU_PROPERTY_{X86|AARCH64}_FEATURE_1_AND from the object crate. --- compiler/rustc_codegen_ssa/src/back/metadata.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index a463dff852d..1f827a2375d 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -12,7 +12,6 @@ use object::{ use snap::write::FrameEncoder; -use object::elf::NT_GNU_PROPERTY_TYPE_0; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice}; use rustc_metadata::fs::METADATA_FILENAME; @@ -124,7 +123,7 @@ fn add_gnu_property_note( let mut data: Vec = Vec::new(); let n_namsz: u32 = 4; // Size of the n_name field let n_descsz: u32 = 16; // Size of the n_desc field - let n_type: u32 = NT_GNU_PROPERTY_TYPE_0; // Type of note descriptor + let n_type: u32 = object::elf::NT_GNU_PROPERTY_TYPE_0; // Type of note descriptor let header_values = [n_namsz, n_descsz, n_type]; header_values.iter().for_each(|v| { data.extend_from_slice(&match endianness { @@ -134,8 +133,8 @@ fn add_gnu_property_note( }); data.extend_from_slice(b"GNU\0"); // Owner of the program property note let pr_type: u32 = match architecture { - Architecture::X86_64 => 0xc0000002, - Architecture::Aarch64 => 0xc0000000, + Architecture::X86_64 => object::elf::GNU_PROPERTY_X86_FEATURE_1_AND, + Architecture::Aarch64 => object::elf::GNU_PROPERTY_AARCH64_FEATURE_1_AND, _ => unreachable!(), }; let pr_datasz: u32 = 4; //size of the pr_data field From 934e7e6c26cc9c78a176a48c3e7d2b9fff501dd8 Mon Sep 17 00:00:00 2001 From: jyn Date: Wed, 5 Jul 2023 11:38:55 -0500 Subject: [PATCH 47/50] Move `ci_rustc_dir` to Config and use it consistently --- src/bootstrap/compile.rs | 4 ++-- src/bootstrap/config.rs | 6 ++++++ src/bootstrap/download.rs | 2 +- src/bootstrap/lib.rs | 5 ----- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 14c3ef79a78..53197212b2e 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -645,8 +645,8 @@ fn cp_rustc_component_to_ci_sysroot( contents: Vec, ) { let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false }); + let ci_rustc_dir = builder.config.ci_rustc_dir(); - let ci_rustc_dir = builder.out.join(&*builder.build.build.triple).join("ci-rustc"); for file in contents { let src = ci_rustc_dir.join(&file); let dst = sysroot.join(file); @@ -1381,7 +1381,7 @@ impl Step for Sysroot { // FIXME: this is wrong when compiler.host != build, but we don't support that today OsStr::new(std::env::consts::DLL_EXTENSION), ]; - let ci_rustc_dir = builder.ci_rustc_dir(builder.config.build); + let ci_rustc_dir = builder.config.ci_rustc_dir(); builder.cp_filtered(&ci_rustc_dir, &sysroot, &|path| { if path.extension().map_or(true, |ext| !filtered_extensions.contains(&ext)) { return true; diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index af29fe0baae..bf4bf4f938c 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -1800,6 +1800,12 @@ impl Config { self.out.join(&*self.build.triple).join("ci-llvm") } + /// Directory where the extracted `rustc-dev` component is stored. + pub(crate) fn ci_rustc_dir(&self) -> PathBuf { + assert!(self.download_rustc()); + self.out.join(self.build.triple).join("ci-rustc") + } + /// Determine whether llvm should be linked dynamically. /// /// If `false`, llvm should be linked statically. diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs index 90578065ba2..a081f6189d7 100644 --- a/src/bootstrap/download.rs +++ b/src/bootstrap/download.rs @@ -406,7 +406,7 @@ impl Config { return vec![]; } - let ci_rustc_dir = self.out.join(&*self.build.triple).join("ci-rustc"); + let ci_rustc_dir = self.ci_rustc_dir(); let stamp_file = ci_rustc_dir.join(stamp_file); let contents_file = t!(File::open(&stamp_file), stamp_file.display().to_string()); t!(BufReader::new(contents_file).lines().collect()) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 6a51450a777..0dded6d011f 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -819,11 +819,6 @@ impl Build { self.stage_out(compiler, mode).join(&*target.triple).join(self.cargo_dir()) } - /// Directory where the extracted `rustc-dev` component is stored. - fn ci_rustc_dir(&self, target: TargetSelection) -> PathBuf { - self.out.join(&*target.triple).join("ci-rustc") - } - /// Root output directory for LLVM compiled for `target` /// /// Note that if LLVM is configured externally then the directory returned From 30e34f3857368ab3a4a321206c44aa5bf1db23e0 Mon Sep 17 00:00:00 2001 From: jyn Date: Sat, 8 Jul 2023 14:50:57 -0500 Subject: [PATCH 48/50] Don't depend on crate names in tests/ui-fulldeps/missing-rustc-driver-error.rs Not only are they a pain to update, but they differ depending on whether `parallel-rustc` is enabled or not --- tests/ui-fulldeps/missing-rustc-driver-error.rs | 4 ++-- tests/ui-fulldeps/missing-rustc-driver-error.stderr | 12 +----------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/tests/ui-fulldeps/missing-rustc-driver-error.rs b/tests/ui-fulldeps/missing-rustc-driver-error.rs index 654cd6f6dc9..b627a207c98 100644 --- a/tests/ui-fulldeps/missing-rustc-driver-error.rs +++ b/tests/ui-fulldeps/missing-rustc-driver-error.rs @@ -1,8 +1,8 @@ // Test that we get the following hint when trying to use a compiler crate without rustc_driver. // error-pattern: try adding `extern crate rustc_driver;` at the top level of this crate // compile-flags: --emit link -// The exactly list of required crates depends on the target. as such only test Unix targets. -// only-unix +// normalize-stderr-test ".*crate .* required.*\n\n" -> "" +// normalize-stderr-test: "aborting due to [0-9]+" -> "aborting due to NUMBER" #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/missing-rustc-driver-error.stderr b/tests/ui-fulldeps/missing-rustc-driver-error.stderr index 939e888e5cb..d7bf27d6349 100644 --- a/tests/ui-fulldeps/missing-rustc-driver-error.stderr +++ b/tests/ui-fulldeps/missing-rustc-driver-error.stderr @@ -2,15 +2,5 @@ error: crate `rustc_serialize` required to be available in rlib format, but was | = help: try adding `extern crate rustc_driver;` at the top level of this crate -error: crate `smallvec` required to be available in rlib format, but was not found in this form - -error: crate `thin_vec` required to be available in rlib format, but was not found in this form - -error: crate `indexmap` required to be available in rlib format, but was not found in this form - -error: crate `hashbrown` required to be available in rlib format, but was not found in this form - -error: crate `equivalent` required to be available in rlib format, but was not found in this form - -error: aborting due to 6 previous errors +error: aborting due to NUMBER previous errors From 67b5990472e3cac643d8cf90f45fe42201ddec3c Mon Sep 17 00:00:00 2001 From: jyn Date: Mon, 10 Jul 2023 15:59:30 -0500 Subject: [PATCH 49/50] Revert "Fix `x test lint-docs` when download-rustc is enabled" This was not the correct fix. The problem was two-fold: - `download-rustc` didn't respect `llvm.assertions` - `rust-dev` was missing a bump to `download-ci-llvm-stamp` The first is fixed in this PR and the latter was fixed a while ago. Revert this change to avoid breaking `rpath = false`. --- src/tools/lint-docs/src/groups.rs | 1 - src/tools/lint-docs/src/lib.rs | 6 ------ 2 files changed, 7 deletions(-) diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs index b11fb287cf4..5be8ef7996b 100644 --- a/src/tools/lint-docs/src/groups.rs +++ b/src/tools/lint-docs/src/groups.rs @@ -39,7 +39,6 @@ impl<'a> LintExtractor<'a> { fn collect_groups(&self) -> Result> { let mut result = BTreeMap::new(); let mut cmd = Command::new(self.rustc_path); - cmd.env_remove("LD_LIBRARY_PATH"); cmd.arg("-Whelp"); let output = cmd.output().map_err(|e| format!("failed to run command {:?}\n{}", cmd, e))?; if !output.status.success() { diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs index fe29b9abda3..b7c8b9ed2e3 100644 --- a/src/tools/lint-docs/src/lib.rs +++ b/src/tools/lint-docs/src/lib.rs @@ -403,12 +403,6 @@ impl<'a> LintExtractor<'a> { fs::write(&tempfile, source) .map_err(|e| format!("failed to write {}: {}", tempfile.display(), e))?; let mut cmd = Command::new(self.rustc_path); - // NOTE: bootstrap sets `LD_LIBRARY_PATH` for building lint-docs itself. - // Unfortunately, lint-docs is a bootstrap tool while rustc is built from source, - // and sometimes the paths conflict. In particular, when using `download-rustc`, - // the LLVM versions can differ between `ci-llvm` and `ci-rustc-sysroot`. - // Unset LD_LIBRARY_PATH here so it doesn't interfere with running the compiler. - cmd.env_remove("LD_LIBRARY_PATH"); if options.contains(&"edition2015") { cmd.arg("--edition=2015"); } else { From fb5efd7008c698a821e9c50c3f3a04d48abd8295 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 12 Jul 2023 06:59:57 -0700 Subject: [PATCH 50/50] Ignore flaky clippy tests. --- src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs | 3 +++ src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs | 3 +++ .../clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs | 3 +++ 3 files changed, 9 insertions(+) diff --git a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs index 83db2a07d33..cc36ce5f487 100644 --- a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs +++ b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs @@ -1,4 +1,7 @@ //@aux-build:proc_macro_attr.rs:proc-macro +// Flaky test, see https://github.com/rust-lang/rust/issues/113585. +//@ignore-32bit +//@ignore-64bit #![warn(clippy::empty_line_after_doc_comments)] #![allow(clippy::assertions_on_constants)] #![feature(custom_inner_attributes)] diff --git a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs b/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs index b2d7ddae427..bc54e0fd2de 100644 --- a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs +++ b/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs @@ -1,4 +1,7 @@ //@aux-build:proc_macro_attr.rs:proc-macro +// Flaky test, see https://github.com/rust-lang/rust/issues/113585. +//@ignore-32bit +//@ignore-64bit #![warn(clippy::empty_line_after_outer_attr)] #![allow(clippy::assertions_on_constants)] #![feature(custom_inner_attributes)] diff --git a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs index 876f16a3854..321aa69a1a5 100644 --- a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs +++ b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs @@ -1,4 +1,7 @@ //@aux-build:proc_macro_attr.rs:proc-macro +// Flaky test, see https://github.com/rust-lang/rust/issues/113585. +//@ignore-32bit +//@ignore-64bit #![warn(clippy::needless_arbitrary_self_type)]