From 369555c85a038d4cad396301822cf89627a7e5c6 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Mon, 23 May 2022 02:33:27 +0000 Subject: [PATCH 01/14] Implement `FusedIterator` for `std::net::[Into]Incoming` They never return `None`, so they trivially fulfill the contract. --- library/std/src/net/tcp.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 06300035633b9..2cbc9f22baf78 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -7,6 +7,7 @@ use crate::io::prelude::*; use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut}; +use crate::iter::FusedIterator; use crate::net::{Shutdown, SocketAddr, ToSocketAddrs}; use crate::sys_common::net as net_imp; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -1009,6 +1010,9 @@ impl<'a> Iterator for Incoming<'a> { } } +#[stable(feature = "tcp_listener_incoming_fused_iterator", since = "1.63.0")] +impl FusedIterator for Incoming<'_> {} + #[unstable(feature = "tcplistener_into_incoming", issue = "88339")] impl Iterator for IntoIncoming { type Item = io::Result; @@ -1017,6 +1021,9 @@ impl Iterator for IntoIncoming { } } +#[unstable(feature = "tcplistener_into_incoming", issue = "88339")] +impl FusedIterator for IntoIncoming {} + impl AsInner for TcpListener { fn as_inner(&self) -> &net_imp::TcpListener { &self.0 From c36572c11e0cd179d80b4540890bc046b78a0cb7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 2 Jul 2022 10:53:34 -0400 Subject: [PATCH 02/14] add AllocRange Debug impl; remove redundant AllocId Display impl --- .../rustc_const_eval/src/interpret/memory.rs | 32 ++++++------------- .../src/mir/interpret/allocation.rs | 8 ++++- .../rustc_middle/src/mir/interpret/error.rs | 20 ++++-------- .../rustc_middle/src/mir/interpret/mod.rs | 12 +++---- .../rustc_middle/src/mir/interpret/pointer.rs | 4 +-- .../rustc_middle/src/mir/interpret/value.rs | 2 +- compiler/rustc_middle/src/mir/pretty.rs | 4 +-- compiler/rustc_middle/src/ty/consts/int.rs | 4 +++ 8 files changed, 36 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index d5e68dbd5b7a9..ccf3647f0d90c 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -276,7 +276,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { kind: MemoryKind, ) -> InterpResult<'tcx> { let (alloc_id, offset, tag) = self.ptr_get_alloc_id(ptr)?; - trace!("deallocating: {}", alloc_id); + trace!("deallocating: {alloc_id:?}"); if offset.bytes() != 0 { throw_ub_format!( @@ -289,10 +289,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Deallocating global memory -- always an error return Err(match self.tcx.get_global_alloc(alloc_id) { Some(GlobalAlloc::Function(..)) => { - err_ub_format!("deallocating {}, which is a function", alloc_id) + err_ub_format!("deallocating {alloc_id:?}, which is a function") } Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => { - err_ub_format!("deallocating {}, which is static memory", alloc_id) + err_ub_format!("deallocating {alloc_id:?}, which is static memory") } None => err_ub!(PointerUseAfterFree(alloc_id)), } @@ -302,12 +302,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { debug!(?alloc); if alloc.mutability == Mutability::Not { - throw_ub_format!("deallocating immutable allocation {}", alloc_id); + throw_ub_format!("deallocating immutable allocation {alloc_id:?}"); } if alloc_kind != kind { throw_ub_format!( - "deallocating {}, which is {} memory, using {} deallocation operation", - alloc_id, + "deallocating {alloc_id:?}, which is {} memory, using {} deallocation operation", alloc_kind, kind ); @@ -315,8 +314,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let Some((size, align)) = old_size_and_align { if size != alloc.size() || align != alloc.align { throw_ub_format!( - "incorrect layout on deallocation: {} has size {} and alignment {}, but gave size {} and alignment {}", - alloc_id, + "incorrect layout on deallocation: {alloc_id:?} has size {} and alignment {}, but gave size {} and alignment {}", alloc.size().bytes(), alloc.align.bytes(), size.bytes(), @@ -815,7 +813,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, continue; } - write!(fmt, "{}", id)?; + write!(fmt, "{id:?}")?; match self.ecx.memory.alloc_map.get(id) { Some(&(kind, ref alloc)) => { // normal alloc @@ -865,13 +863,7 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRefMut<'a, 'tcx, Tag, Extra> { val: ScalarMaybeUninit, ) -> InterpResult<'tcx> { let range = self.range.subrange(range); - debug!( - "write_scalar in {} at {:#x}, size {}: {:?}", - self.alloc_id, - range.start.bytes(), - range.size.bytes(), - val - ); + debug!("write_scalar at {:?}{range:?}: {val:?}", self.alloc_id); Ok(self .alloc .write_scalar(&self.tcx, range, val) @@ -906,13 +898,7 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> { .alloc .read_scalar(&self.tcx, range, read_provenance) .map_err(|e| e.to_interp_error(self.alloc_id))?; - debug!( - "read_scalar in {} at {:#x}, size {}: {:?}", - self.alloc_id, - range.start.bytes(), - range.size.bytes(), - res - ); + debug!("read_scalar at {:?}{range:?}: {res:?}", self.alloc_id); Ok(res) } diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 10c4ea63a68b2..b9143802276f7 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -160,12 +160,18 @@ impl AllocError { } /// The information that makes up a memory access: offset and size. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone)] pub struct AllocRange { pub start: Size, pub size: Size, } +impl fmt::Debug for AllocRange { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "[{:#x}..{:#x}]", self.start.bytes(), self.end().bytes()) + } +} + /// Free-starting constructor for less syntactic overhead. #[inline(always)] pub fn alloc_range(start: Size, size: Size) -> AllocRange { diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index a33a2921f573e..dbdbeb0830a41 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -334,36 +334,30 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { p, ), PointerUseAfterFree(a) => { - write!(f, "pointer to {} was dereferenced after this allocation got freed", a) + write!(f, "pointer to {a:?} was dereferenced after this allocation got freed") } PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size: Size::ZERO, msg } => { write!( f, - "{}{alloc_id} has size {alloc_size}, so pointer at offset {ptr_offset} is out-of-bounds", - msg, - alloc_id = alloc_id, + "{msg}{alloc_id:?} has size {alloc_size}, so pointer at offset {ptr_offset} is out-of-bounds", alloc_size = alloc_size.bytes(), - ptr_offset = ptr_offset, ) } PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => write!( f, - "{}{alloc_id} has size {alloc_size}, so pointer to {ptr_size} byte{ptr_size_p} starting at offset {ptr_offset} is out-of-bounds", - msg, - alloc_id = alloc_id, + "{msg}{alloc_id:?} has size {alloc_size}, so pointer to {ptr_size} byte{ptr_size_p} starting at offset {ptr_offset} is out-of-bounds", alloc_size = alloc_size.bytes(), ptr_size = ptr_size.bytes(), ptr_size_p = pluralize!(ptr_size.bytes()), - ptr_offset = ptr_offset, ), DanglingIntPointer(0, CheckInAllocMsg::InboundsTest) => { write!(f, "null pointer is not a valid pointer for this operation") } DanglingIntPointer(0, msg) => { - write!(f, "{}null pointer is not a valid pointer", msg) + write!(f, "{msg}null pointer is not a valid pointer") } DanglingIntPointer(i, msg) => { - write!(f, "{}0x{:x} is not a valid pointer", msg, i) + write!(f, "{msg}{:#x} is not a valid pointer", i) } AlignmentCheckFailed { required, has } => write!( f, @@ -371,8 +365,8 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { has.bytes(), required.bytes() ), - WriteToReadOnly(a) => write!(f, "writing to {} which is read-only", a), - DerefFunctionPointer(a) => write!(f, "accessing {} which contains a function", a), + WriteToReadOnly(a) => write!(f, "writing to {a:?} which is read-only"), + DerefFunctionPointer(a) => write!(f, "accessing {a:?} which contains a function"), ValidationFailure { path: None, msg } => { write!(f, "constructing invalid value: {}", msg) } diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 8733a85ef3fad..8b75483252776 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -190,11 +190,7 @@ impl fmt::Debug for AllocId { } } -impl fmt::Display for AllocId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(self, f) - } -} +// No "Display" since AllocIds are not usually user-visible. #[derive(TyDecodable, TyEncodable)] enum AllocDiscriminant { @@ -470,7 +466,7 @@ impl<'tcx> TyCtxt<'tcx> { return alloc_id; } let id = alloc_map.reserve(); - debug!("creating alloc {:?} with id {}", alloc, id); + debug!("creating alloc {:?} with id {:?}", alloc, id); alloc_map.alloc_map.insert(id, alloc.clone()); alloc_map.dedup.insert(alloc, id); id @@ -538,7 +534,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn global_alloc(self, id: AllocId) -> GlobalAlloc<'tcx> { match self.get_global_alloc(id) { Some(alloc) => alloc, - None => bug!("could not find allocation for {}", id), + None => bug!("could not find allocation for {id:?}"), } } @@ -546,7 +542,7 @@ impl<'tcx> TyCtxt<'tcx> { /// call this function twice, even with the same `Allocation` will ICE the compiler. pub fn set_alloc_id_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) { if let Some(old) = self.alloc_map.lock().alloc_map.insert(id, GlobalAlloc::Memory(mem)) { - bug!("tried to set allocation ID {}, but it was already existing as {:#?}", id, old); + bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}"); } } diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 26da93b9dcebc..81d744107fd56 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -144,7 +144,7 @@ impl Provenance for AllocId { } // Print offset only if it is non-zero. if ptr.offset.bytes() > 0 { - write!(f, "+0x{:x}", ptr.offset.bytes())?; + write!(f, "+{:#x}", ptr.offset.bytes())?; } Ok(()) } @@ -181,7 +181,7 @@ impl fmt::Debug for Pointer> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.provenance { Some(tag) => Provenance::fmt(&Pointer::new(tag, self.offset), f), - None => write!(f, "0x{:x}", self.offset.bytes()), + None => write!(f, "{:#x}", self.offset.bytes()), } } } diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index e80918d5e5d03..8ecbb5ab0b31f 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -167,7 +167,7 @@ impl fmt::LowerHex for Scalar { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Scalar::Ptr(ptr, _size) => write!(f, "pointer to {:?}", ptr), - Scalar::Int(int) => write!(f, "0x{:x}", int), + Scalar::Int(int) => write!(f, "{:#x}", int), } } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 462c0ada3cf87..24c6cd91d0a54 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -716,12 +716,12 @@ pub fn write_allocations<'tcx>( } write!(w, "{}", display_allocation(tcx, alloc.inner())) }; - write!(w, "\n{}", id)?; + write!(w, "\n{id:?}")?; match tcx.get_global_alloc(id) { // This can't really happen unless there are bugs, but it doesn't cost us anything to // gracefully handle it and allow buggy rustc to be debugged via allocation printing. None => write!(w, " (deallocated)")?, - Some(GlobalAlloc::Function(inst)) => write!(w, " (fn: {})", inst)?, + Some(GlobalAlloc::Function(inst)) => write!(w, " (fn: {inst})")?, Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => { match tcx.eval_static_initializer(did) { Ok(alloc) => { diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 51e51a63fd043..c7c2692281ebb 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -452,6 +452,10 @@ impl fmt::Debug for ScalarInt { impl fmt::LowerHex for ScalarInt { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.check_data(); + if f.alternate() { + // Like regular ints, alternate flag adds leading `0x`. + write!(f, "0x")?; + } // Format as hex number wide enough to fit any value of the given `size`. // So data=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014". // Using a block `{self.data}` here to force a copy instead of using `self.data` From d31cbb51505f4ca8c25b1b11abe3d10ad8171b06 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 2 Jul 2022 11:00:12 -0400 Subject: [PATCH 03/14] make AllocRef APIs more consistent --- compiler/rustc_const_eval/src/interpret/memory.rs | 14 ++++++++------ compiler/rustc_const_eval/src/interpret/traits.rs | 10 +++++----- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index ccf3647f0d90c..de6200ef01252 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -857,6 +857,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, /// Reading and writing. impl<'tcx, 'a, Tag: Provenance, Extra> AllocRefMut<'a, 'tcx, Tag, Extra> { + /// `range` is relative to this allocation reference, not the base of the allocation. pub fn write_scalar( &mut self, range: AllocRange, @@ -870,6 +871,7 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRefMut<'a, 'tcx, Tag, Extra> { .map_err(|e| e.to_interp_error(self.alloc_id))?) } + /// `offset` is relative to this allocation reference, not the base of the allocation. pub fn write_ptr_sized( &mut self, offset: Size, @@ -888,6 +890,7 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRefMut<'a, 'tcx, Tag, Extra> { } impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> { + /// `range` is relative to this allocation reference, not the base of the allocation. pub fn read_scalar( &self, range: AllocRange, @@ -902,14 +905,12 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> { Ok(res) } - pub fn read_integer( - &self, - offset: Size, - size: Size, - ) -> InterpResult<'tcx, ScalarMaybeUninit> { - self.read_scalar(alloc_range(offset, size), /*read_provenance*/ false) + /// `range` is relative to this allocation reference, not the base of the allocation. + pub fn read_integer(&self, range: AllocRange) -> InterpResult<'tcx, ScalarMaybeUninit> { + self.read_scalar(range, /*read_provenance*/ false) } + /// `offset` is relative to this allocation reference, not the base of the allocation. pub fn read_pointer(&self, offset: Size) -> InterpResult<'tcx, ScalarMaybeUninit> { self.read_scalar( alloc_range(offset, self.tcx.data_layout().pointer_size), @@ -917,6 +918,7 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> { ) } + /// `range` is relative to this allocation reference, not the base of the allocation. pub fn check_bytes( &self, range: AllocRange, diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index 9c48f3e833760..22c23df7b1ab3 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -1,6 +1,6 @@ use std::convert::TryFrom; -use rustc_middle::mir::interpret::{InterpResult, Pointer, PointerArithmetic}; +use rustc_middle::mir::interpret::{alloc_range, InterpResult, Pointer, PointerArithmetic}; use rustc_middle::ty::{ self, Ty, TyCtxt, COMMON_VTABLE_ENTRIES_ALIGN, COMMON_VTABLE_ENTRIES_DROPINPLACE, COMMON_VTABLE_ENTRIES_SIZE, @@ -102,18 +102,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { )? .expect("cannot be a ZST"); let size = vtable - .read_integer( + .read_integer(alloc_range( pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_SIZE).unwrap(), pointer_size, - )? + ))? .check_init()?; let size = size.to_machine_usize(self)?; let size = Size::from_bytes(size); let align = vtable - .read_integer( + .read_integer(alloc_range( pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_ALIGN).unwrap(), pointer_size, - )? + ))? .check_init()?; let align = align.to_machine_usize(self)?; let align = Align::from_bytes(align).map_err(|e| err_ub!(InvalidVtableAlignment(e)))?; From 0832d1d02280e17cfa083b068d2def4b1844cd10 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 2 Jul 2022 13:37:24 -0400 Subject: [PATCH 04/14] more use of format! variable capture Co-authored-by: Joe ST --- compiler/rustc_const_eval/src/interpret/memory.rs | 4 +--- compiler/rustc_middle/src/mir/interpret/error.rs | 2 +- compiler/rustc_middle/src/mir/interpret/mod.rs | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index de6200ef01252..86d5bb37d55a5 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -306,9 +306,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } if alloc_kind != kind { throw_ub_format!( - "deallocating {alloc_id:?}, which is {} memory, using {} deallocation operation", - alloc_kind, - kind + "deallocating {alloc_id:?}, which is {alloc_kind} memory, using {kind} deallocation operation" ); } if let Some((size, align)) = old_size_and_align { diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index dbdbeb0830a41..f30769248c074 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -357,7 +357,7 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { write!(f, "{msg}null pointer is not a valid pointer") } DanglingIntPointer(i, msg) => { - write!(f, "{msg}{:#x} is not a valid pointer", i) + write!(f, "{msg}{i:#x} is not a valid pointer") } AlignmentCheckFailed { required, has } => write!( f, diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 8b75483252776..698024b23301e 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -466,7 +466,7 @@ impl<'tcx> TyCtxt<'tcx> { return alloc_id; } let id = alloc_map.reserve(); - debug!("creating alloc {:?} with id {:?}", alloc, id); + debug!("creating alloc {alloc:?} with id {id:?}"); alloc_map.alloc_map.insert(id, alloc.clone()); alloc_map.dedup.insert(alloc, id); id From 76c0429d86041665dcf05682cd6579d8d2ab153c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 2 Jul 2022 11:02:54 -0700 Subject: [PATCH 05/14] Bump std::net::Incoming FusedIterator impl to Rust 1.64 --- library/std/src/net/tcp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 2cbc9f22baf78..69b72a81c5b6d 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -1010,7 +1010,7 @@ impl<'a> Iterator for Incoming<'a> { } } -#[stable(feature = "tcp_listener_incoming_fused_iterator", since = "1.63.0")] +#[stable(feature = "tcp_listener_incoming_fused_iterator", since = "1.64.0")] impl FusedIterator for Incoming<'_> {} #[unstable(feature = "tcplistener_into_incoming", issue = "88339")] From 46ccde4408ebbab3bae249072bb486b9b25d9e96 Mon Sep 17 00:00:00 2001 From: KaDiWa Date: Sun, 3 Jul 2022 18:51:14 +0200 Subject: [PATCH 06/14] clean up the borrowing in rustc_hir_pretty a lot of the `&`s and `ref`s were redundant --- compiler/rustc_hir_pretty/src/lib.rs | 545 +++++++++++++-------------- 1 file changed, 264 insertions(+), 281 deletions(-) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index fd843b0c403a6..50acb0270b0be 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -59,7 +59,7 @@ impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> { Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)), Nested::ForeignItem(id) => state.print_foreign_item(self.foreign_item(id)), Nested::Body(id) => state.print_expr(&self.body(id).value), - Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat), + Nested::BodyParamPat(id, i) => state.print_pat(self.body(id).params[i].pat), } } } @@ -74,37 +74,37 @@ pub struct State<'a> { impl<'a> State<'a> { pub fn print_node(&mut self, node: Node<'_>) { match node { - Node::Param(a) => self.print_param(&a), - Node::Item(a) => self.print_item(&a), - Node::ForeignItem(a) => self.print_foreign_item(&a), + Node::Param(a) => self.print_param(a), + Node::Item(a) => self.print_item(a), + Node::ForeignItem(a) => self.print_foreign_item(a), Node::TraitItem(a) => self.print_trait_item(a), Node::ImplItem(a) => self.print_impl_item(a), - Node::Variant(a) => self.print_variant(&a), - Node::AnonConst(a) => self.print_anon_const(&a), - Node::Expr(a) => self.print_expr(&a), - Node::Stmt(a) => self.print_stmt(&a), - Node::PathSegment(a) => self.print_path_segment(&a), - Node::Ty(a) => self.print_type(&a), - Node::TypeBinding(a) => self.print_type_binding(&a), - Node::TraitRef(a) => self.print_trait_ref(&a), - Node::Pat(a) => self.print_pat(&a), - Node::Arm(a) => self.print_arm(&a), + Node::Variant(a) => self.print_variant(a), + Node::AnonConst(a) => self.print_anon_const(a), + Node::Expr(a) => self.print_expr(a), + Node::Stmt(a) => self.print_stmt(a), + Node::PathSegment(a) => self.print_path_segment(a), + Node::Ty(a) => self.print_type(a), + Node::TypeBinding(a) => self.print_type_binding(a), + Node::TraitRef(a) => self.print_trait_ref(a), + Node::Pat(a) => self.print_pat(a), + Node::Arm(a) => self.print_arm(a), Node::Infer(_) => self.word("_"), Node::Block(a) => { // Containing cbox, will be closed by print-block at `}`. self.cbox(INDENT_UNIT); // Head-ibox, will be closed by print-block after `{`. self.ibox(0); - self.print_block(&a) + self.print_block(a); } - Node::Lifetime(a) => self.print_lifetime(&a), + Node::Lifetime(a) => self.print_lifetime(a), Node::GenericParam(_) => panic!("cannot print Node::GenericParam"), Node::Field(_) => panic!("cannot print Node::Field"), // These cases do not carry enough information in the // `hir_map` to reconstruct their full structure for pretty // printing. Node::Ctor(..) => panic!("cannot print isolated Ctor"), - Node::Local(a) => self.print_local_decl(&a), + Node::Local(a) => self.print_local_decl(a), Node::Crate(..) => panic!("cannot print Crate"), } } @@ -266,7 +266,7 @@ impl<'a> State<'a> { } pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[hir::Expr<'_>]) { - self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&e), |e| e.span) + self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span); } pub fn print_mod(&mut self, _mod: &hir::Mod<'_>, attrs: &[ast::Attribute]) { @@ -287,9 +287,9 @@ impl<'a> State<'a> { self.maybe_print_comment(ty.span.lo()); self.ibox(0); match ty.kind { - hir::TyKind::Slice(ref ty) => { + hir::TyKind::Slice(ty) => { self.word("["); - self.print_type(&ty); + self.print_type(ty); self.word("]"); } hir::TyKind::Ptr(ref mt) => { @@ -304,23 +304,16 @@ impl<'a> State<'a> { hir::TyKind::Never => { self.word("!"); } - hir::TyKind::Tup(ref elts) => { + hir::TyKind::Tup(elts) => { self.popen(); - self.commasep(Inconsistent, &elts, |s, ty| s.print_type(&ty)); + self.commasep(Inconsistent, elts, |s, ty| s.print_type(ty)); if elts.len() == 1 { self.word(","); } self.pclose(); } - hir::TyKind::BareFn(ref f) => { - self.print_ty_fn( - f.abi, - f.unsafety, - &f.decl, - None, - &f.generic_params, - f.param_names, - ); + hir::TyKind::BareFn(f) => { + self.print_ty_fn(f.abi, f.unsafety, f.decl, None, f.generic_params, f.param_names); } hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"), hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false), @@ -344,9 +337,9 @@ impl<'a> State<'a> { self.print_lifetime(lifetime); } } - hir::TyKind::Array(ref ty, ref length) => { + hir::TyKind::Array(ty, ref length) => { self.word("["); - self.print_type(&ty); + self.print_type(ty); self.word("; "); self.print_array_length(length); self.word("]"); @@ -373,7 +366,7 @@ impl<'a> State<'a> { self.maybe_print_comment(item.span.lo()); self.print_outer_attributes(self.attrs(item.hir_id())); match item.kind { - hir::ForeignItemKind::Fn(ref decl, ref arg_names, ref generics) => { + hir::ForeignItemKind::Fn(decl, arg_names, generics) => { self.head(""); self.print_fn( decl, @@ -392,14 +385,14 @@ impl<'a> State<'a> { self.word(";"); self.end() // end the outer fn box } - hir::ForeignItemKind::Static(ref t, m) => { + hir::ForeignItemKind::Static(t, m) => { self.head("static"); if m == hir::Mutability::Mut { self.word_space("mut"); } self.print_ident(item.ident); self.word_space(":"); - self.print_type(&t); + self.print_type(t); self.word(";"); self.end(); // end the head-ibox self.end() // end the outer cbox @@ -442,7 +435,7 @@ impl<'a> State<'a> { ) { self.word_space("type"); self.print_ident(ident); - self.print_generic_params(&generics.params); + self.print_generic_params(generics.params); if let Some(bounds) = bounds { self.print_bounds(":", bounds); } @@ -463,7 +456,7 @@ impl<'a> State<'a> { ) { self.head("type"); self.print_ident(item.ident); - self.print_generic_params(&generics.params); + self.print_generic_params(generics.params); self.end(); // end the inner ibox self.print_where_clause(generics); @@ -494,7 +487,7 @@ impl<'a> State<'a> { self.end(); // end inner head-block self.end(); // end outer head-block } - hir::ItemKind::Use(ref path, kind) => { + hir::ItemKind::Use(path, kind) => { self.head("use"); self.print_path(path, false); @@ -513,14 +506,14 @@ impl<'a> State<'a> { self.end(); // end inner head-block self.end(); // end outer head-block } - hir::ItemKind::Static(ref ty, m, expr) => { + hir::ItemKind::Static(ty, m, expr) => { self.head("static"); if m == hir::Mutability::Mut { self.word_space("mut"); } self.print_ident(item.ident); self.word_space(":"); - self.print_type(&ty); + self.print_type(ty); self.space(); self.end(); // end the head-ibox @@ -529,11 +522,11 @@ impl<'a> State<'a> { self.word(";"); self.end(); // end the outer cbox } - hir::ItemKind::Const(ref ty, expr) => { + hir::ItemKind::Const(ty, expr) => { self.head("const"); self.print_ident(item.ident); self.word_space(":"); - self.print_type(&ty); + self.print_type(ty); self.space(); self.end(); // end the head-ibox @@ -542,10 +535,10 @@ impl<'a> State<'a> { self.word(";"); self.end(); // end the outer cbox } - hir::ItemKind::Fn(ref sig, ref param_names, body) => { + hir::ItemKind::Fn(ref sig, param_names, body) => { self.head(""); self.print_fn( - &sig.decl, + sig.decl, sig.header, Some(item.ident.name), param_names, @@ -578,22 +571,22 @@ impl<'a> State<'a> { } self.bclose(item.span); } - hir::ItemKind::GlobalAsm(ref asm) => { + hir::ItemKind::GlobalAsm(asm) => { self.head("global_asm!"); self.print_inline_asm(asm); self.end() } - hir::ItemKind::TyAlias(ref ty, ref generics) => { - self.print_item_type(item, &generics, |state| { + hir::ItemKind::TyAlias(ty, generics) => { + self.print_item_type(item, generics, |state| { state.word_space("="); - state.print_type(&ty); + state.print_type(ty); }); } hir::ItemKind::OpaqueTy(ref opaque_ty) => { - self.print_item_type(item, &opaque_ty.generics, |state| { + self.print_item_type(item, opaque_ty.generics, |state| { let mut real_bounds = Vec::with_capacity(opaque_ty.bounds.len()); - for b in opaque_ty.bounds.iter() { - if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { + for b in opaque_ty.bounds { + if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b { state.space(); state.word_space("for ?"); state.print_trait_ref(&ptr.trait_ref); @@ -604,39 +597,39 @@ impl<'a> State<'a> { state.print_bounds("= impl", real_bounds); }); } - hir::ItemKind::Enum(ref enum_definition, ref params) => { + hir::ItemKind::Enum(ref enum_definition, params) => { self.print_enum_def(enum_definition, params, item.ident.name, item.span); } - hir::ItemKind::Struct(ref struct_def, ref generics) => { + hir::ItemKind::Struct(ref struct_def, generics) => { self.head("struct"); self.print_struct(struct_def, generics, item.ident.name, item.span, true); } - hir::ItemKind::Union(ref struct_def, ref generics) => { + hir::ItemKind::Union(ref struct_def, generics) => { self.head("union"); self.print_struct(struct_def, generics, item.ident.name, item.span, true); } - hir::ItemKind::Impl(hir::Impl { + hir::ItemKind::Impl(&hir::Impl { unsafety, polarity, defaultness, constness, defaultness_span: _, - ref generics, + generics, ref of_trait, - ref self_ty, + self_ty, items, }) => { self.head(""); - self.print_defaultness(*defaultness); - self.print_unsafety(*unsafety); + self.print_defaultness(defaultness); + self.print_unsafety(unsafety); self.word_nbsp("impl"); if !generics.params.is_empty() { - self.print_generic_params(&generics.params); + self.print_generic_params(generics.params); self.space(); } - if *constness == hir::Constness::Const { + if constness == hir::Constness::Const { self.word_nbsp("const"); } @@ -644,33 +637,33 @@ impl<'a> State<'a> { self.word("!"); } - if let Some(ref t) = of_trait { + if let Some(t) = of_trait { self.print_trait_ref(t); self.space(); self.word_space("for"); } - self.print_type(&self_ty); + self.print_type(self_ty); self.print_where_clause(generics); self.space(); self.bopen(); self.print_inner_attributes(attrs); - for impl_item in *items { + for impl_item in items { self.ann.nested(self, Nested::ImplItem(impl_item.id)); } self.bclose(item.span); } - hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, trait_items) => { + hir::ItemKind::Trait(is_auto, unsafety, generics, bounds, trait_items) => { self.head(""); self.print_is_auto(is_auto); self.print_unsafety(unsafety); self.word_nbsp("trait"); self.print_ident(item.ident); - self.print_generic_params(&generics.params); + self.print_generic_params(generics.params); let mut real_bounds = Vec::with_capacity(bounds.len()); - for b in bounds.iter() { - if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { + for b in bounds { + if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b { self.space(); self.word_space("for ?"); self.print_trait_ref(&ptr.trait_ref); @@ -687,14 +680,14 @@ impl<'a> State<'a> { } self.bclose(item.span); } - hir::ItemKind::TraitAlias(ref generics, ref bounds) => { + hir::ItemKind::TraitAlias(generics, bounds) => { self.head("trait"); self.print_ident(item.ident); - self.print_generic_params(&generics.params); + self.print_generic_params(generics.params); let mut real_bounds = Vec::with_capacity(bounds.len()); // FIXME(durka) this seems to be some quite outdated syntax - for b in bounds.iter() { - if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { + for b in bounds { + if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b { self.space(); self.word_space("for ?"); self.print_trait_ref(&ptr.trait_ref); @@ -714,7 +707,7 @@ impl<'a> State<'a> { } pub fn print_trait_ref(&mut self, t: &hir::TraitRef<'_>) { - self.print_path(&t.path, false) + self.print_path(t.path, false); } fn print_formal_generic_params(&mut self, generic_params: &[hir::GenericParam<'_>]) { @@ -726,8 +719,8 @@ impl<'a> State<'a> { } fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef<'_>) { - self.print_formal_generic_params(&t.bound_generic_params); - self.print_trait_ref(&t.trait_ref) + self.print_formal_generic_params(t.bound_generic_params); + self.print_trait_ref(&t.trait_ref); } pub fn print_enum_def( @@ -739,10 +732,10 @@ impl<'a> State<'a> { ) { self.head("enum"); self.print_name(name); - self.print_generic_params(&generics.params); + self.print_generic_params(generics.params); self.print_where_clause(generics); self.space(); - self.print_variants(&enum_definition.variants, span) + self.print_variants(enum_definition.variants, span); } pub fn print_variants(&mut self, variants: &[hir::Variant<'_>], span: rustc_span::Span) { @@ -776,7 +769,7 @@ impl<'a> State<'a> { print_finalizer: bool, ) { self.print_name(name); - self.print_generic_params(&generics.params); + self.print_generic_params(generics.params); match struct_def { hir::VariantData::Tuple(..) | hir::VariantData::Unit(..) => { if let hir::VariantData::Tuple(..) = struct_def { @@ -784,7 +777,7 @@ impl<'a> State<'a> { self.commasep(Inconsistent, struct_def.fields(), |s, field| { s.maybe_print_comment(field.span.lo()); s.print_outer_attributes(s.attrs(field.hir_id)); - s.print_type(&field.ty) + s.print_type(field.ty); }); self.pclose(); } @@ -807,7 +800,7 @@ impl<'a> State<'a> { self.print_outer_attributes(self.attrs(field.hir_id)); self.print_ident(field.ident); self.word_nbsp(":"); - self.print_type(&field.ty); + self.print_type(field.ty); self.word(","); } @@ -819,7 +812,7 @@ impl<'a> State<'a> { pub fn print_variant(&mut self, v: &hir::Variant<'_>) { self.head(""); let generics = hir::Generics::empty(); - self.print_struct(&v.data, &generics, v.ident.name, v.span, false); + self.print_struct(&v.data, generics, v.ident.name, v.span, false); if let Some(ref d) = v.disr_expr { self.space(); self.word_space("="); @@ -834,7 +827,7 @@ impl<'a> State<'a> { arg_names: &[Ident], body_id: Option, ) { - self.print_fn(&m.decl, m.header, Some(ident.name), generics, arg_names, body_id) + self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_names, body_id); } pub fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) { @@ -843,28 +836,23 @@ impl<'a> State<'a> { self.maybe_print_comment(ti.span.lo()); self.print_outer_attributes(self.attrs(ti.hir_id())); match ti.kind { - hir::TraitItemKind::Const(ref ty, default) => { - self.print_associated_const(ti.ident, &ty, default); + hir::TraitItemKind::Const(ty, default) => { + self.print_associated_const(ti.ident, ty, default); } - hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref arg_names)) => { - self.print_method_sig(ti.ident, sig, &ti.generics, arg_names, None); + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_names)) => { + self.print_method_sig(ti.ident, sig, ti.generics, arg_names, None); self.word(";"); } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { self.head(""); - self.print_method_sig(ti.ident, sig, &ti.generics, &[], Some(body)); + self.print_method_sig(ti.ident, sig, ti.generics, &[], Some(body)); self.nbsp(); self.end(); // need to close a box self.end(); // need to close a box self.ann.nested(self, Nested::Body(body)); } - hir::TraitItemKind::Type(ref bounds, ref default) => { - self.print_associated_type( - ti.ident, - &ti.generics, - Some(bounds), - default.as_ref().map(|ty| &**ty), - ); + hir::TraitItemKind::Type(bounds, default) => { + self.print_associated_type(ti.ident, ti.generics, Some(bounds), default); } } self.ann.post(self, AnnNode::SubItem(ti.hir_id())) @@ -877,19 +865,19 @@ impl<'a> State<'a> { self.print_outer_attributes(self.attrs(ii.hir_id())); match ii.kind { - hir::ImplItemKind::Const(ref ty, expr) => { - self.print_associated_const(ii.ident, &ty, Some(expr)); + hir::ImplItemKind::Const(ty, expr) => { + self.print_associated_const(ii.ident, ty, Some(expr)); } hir::ImplItemKind::Fn(ref sig, body) => { self.head(""); - self.print_method_sig(ii.ident, sig, &ii.generics, &[], Some(body)); + self.print_method_sig(ii.ident, sig, ii.generics, &[], Some(body)); self.nbsp(); self.end(); // need to close a box self.end(); // need to close a box self.ann.nested(self, Nested::Body(body)); } - hir::ImplItemKind::TyAlias(ref ty) => { - self.print_associated_type(ii.ident, &ii.generics, None, Some(ty)); + hir::ImplItemKind::TyAlias(ty) => { + self.print_associated_type(ii.ident, ii.generics, None, Some(ty)); } } self.ann.post(self, AnnNode::SubItem(ii.hir_id())) @@ -904,10 +892,10 @@ impl<'a> State<'a> { decl(self); self.end(); - if let Some(ref init) = init { + if let Some(init) = init { self.nbsp(); self.word_space("="); - self.print_expr(&init); + self.print_expr(init); } self.end() } @@ -915,17 +903,17 @@ impl<'a> State<'a> { pub fn print_stmt(&mut self, st: &hir::Stmt<'_>) { self.maybe_print_comment(st.span.lo()); match st.kind { - hir::StmtKind::Local(ref loc) => { - self.print_local(loc.init, |this| this.print_local_decl(&loc)); + hir::StmtKind::Local(loc) => { + self.print_local(loc.init, |this| this.print_local_decl(loc)); } hir::StmtKind::Item(item) => self.ann.nested(self, Nested::Item(item)), - hir::StmtKind::Expr(ref expr) => { + hir::StmtKind::Expr(expr) => { self.space_if_not_bol(); - self.print_expr(&expr); + self.print_expr(expr); } - hir::StmtKind::Semi(ref expr) => { + hir::StmtKind::Semi(expr) => { self.space_if_not_bol(); - self.print_expr(&expr); + self.print_expr(expr); self.word(";"); } } @@ -966,9 +954,9 @@ impl<'a> State<'a> { for st in blk.stmts { self.print_stmt(st); } - if let Some(ref expr) = blk.expr { + if let Some(expr) = blk.expr { self.space_if_not_bol(); - self.print_expr(&expr); + self.print_expr(expr); self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi())); } self.bclose_maybe_open(blk.span, close_box); @@ -979,21 +967,21 @@ impl<'a> State<'a> { if let Some(els_inner) = els { match els_inner.kind { // Another `else if` block. - hir::ExprKind::If(ref i, ref then, ref e) => { + hir::ExprKind::If(i, then, e) => { self.cbox(INDENT_UNIT - 1); self.ibox(0); self.word(" else if "); - self.print_expr_as_cond(&i); + self.print_expr_as_cond(i); self.space(); - self.print_expr(&then); - self.print_else(e.as_ref().map(|e| &**e)) + self.print_expr(then); + self.print_else(e); } // Final `else` block. - hir::ExprKind::Block(ref b, _) => { + hir::ExprKind::Block(b, _) => { self.cbox(INDENT_UNIT - 1); self.ibox(0); self.word(" else "); - self.print_block(&b) + self.print_block(b); } // Constraints would be great here! _ => { @@ -1048,7 +1036,7 @@ impl<'a> State<'a> { if needs_par { self.popen(); } - if let hir::ExprKind::DropTemps(ref actual_expr) = expr.kind { + if let hir::ExprKind::DropTemps(actual_expr) = expr.kind { self.print_expr(actual_expr); } else { self.print_expr(expr); @@ -1114,7 +1102,7 @@ impl<'a> State<'a> { &mut self, qpath: &hir::QPath<'_>, fields: &[hir::ExprField<'_>], - wth: &Option<&hir::Expr<'_>>, + wth: Option<&hir::Expr<'_>>, ) { self.print_qpath(qpath, true); self.word("{"); @@ -1127,28 +1115,24 @@ impl<'a> State<'a> { s.print_ident(field.ident); s.word_space(":"); } - s.print_expr(&field.expr); + s.print_expr(field.expr); s.end() }, |f| f.span, ); - match *wth { - Some(ref expr) => { - self.ibox(INDENT_UNIT); - if !fields.is_empty() { - self.word(","); - self.space(); - } - self.word(".."); - self.print_expr(&expr); - self.end(); - } - _ => { - if !fields.is_empty() { - self.word(",") - } + if let Some(expr) = wth { + self.ibox(INDENT_UNIT); + if !fields.is_empty() { + self.word(","); + self.space(); } + self.word(".."); + self.print_expr(expr); + self.end(); + } else if !fields.is_empty() { + self.word(","); } + self.word("}"); } @@ -1249,18 +1233,17 @@ impl<'a> State<'a> { Options(ast::InlineAsmOptions), } - let mut args = - vec![AsmArg::Template(ast::InlineAsmTemplatePiece::to_string(&asm.template))]; + let mut args = vec![AsmArg::Template(ast::InlineAsmTemplatePiece::to_string(asm.template))]; args.extend(asm.operands.iter().map(|(o, _)| AsmArg::Operand(o))); if !asm.options.is_empty() { args.push(AsmArg::Options(asm.options)); } self.popen(); - self.commasep(Consistent, &args, |s, arg| match arg { - AsmArg::Template(template) => s.print_string(&template, ast::StrStyle::Cooked), - AsmArg::Operand(op) => match op { - hir::InlineAsmOperand::In { reg, expr } => { + self.commasep(Consistent, &args, |s, arg| match *arg { + AsmArg::Template(ref template) => s.print_string(template, ast::StrStyle::Cooked), + AsmArg::Operand(op) => match *op { + hir::InlineAsmOperand::In { reg, ref expr } => { s.word("in"); s.popen(); s.word(format!("{}", reg)); @@ -1268,8 +1251,8 @@ impl<'a> State<'a> { s.space(); s.print_expr(expr); } - hir::InlineAsmOperand::Out { reg, late, expr } => { - s.word(if *late { "lateout" } else { "out" }); + hir::InlineAsmOperand::Out { reg, late, ref expr } => { + s.word(if late { "lateout" } else { "out" }); s.popen(); s.word(format!("{}", reg)); s.pclose(); @@ -1279,16 +1262,16 @@ impl<'a> State<'a> { None => s.word("_"), } } - hir::InlineAsmOperand::InOut { reg, late, expr } => { - s.word(if *late { "inlateout" } else { "inout" }); + hir::InlineAsmOperand::InOut { reg, late, ref expr } => { + s.word(if late { "inlateout" } else { "inout" }); s.popen(); s.word(format!("{}", reg)); s.pclose(); s.space(); s.print_expr(expr); } - hir::InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => { - s.word(if *late { "inlateout" } else { "inout" }); + hir::InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => { + s.word(if late { "inlateout" } else { "inout" }); s.popen(); s.word(format!("{}", reg)); s.pclose(); @@ -1301,17 +1284,17 @@ impl<'a> State<'a> { None => s.word("_"), } } - hir::InlineAsmOperand::Const { anon_const } => { + hir::InlineAsmOperand::Const { ref anon_const } => { s.word("const"); s.space(); s.print_anon_const(anon_const); } - hir::InlineAsmOperand::SymFn { anon_const } => { + hir::InlineAsmOperand::SymFn { ref anon_const } => { s.word("sym_fn"); s.space(); s.print_anon_const(anon_const); } - hir::InlineAsmOperand::SymStatic { path, def_id: _ } => { + hir::InlineAsmOperand::SymStatic { ref path, def_id: _ } => { s.word("sym_static"); s.space(); s.print_qpath(path, true); @@ -1363,57 +1346,57 @@ impl<'a> State<'a> { self.ibox(INDENT_UNIT); self.ann.pre(self, AnnNode::Expr(expr)); match expr.kind { - hir::ExprKind::Box(ref expr) => { + hir::ExprKind::Box(expr) => { self.word_space("box"); self.print_expr_maybe_paren(expr, parser::PREC_PREFIX); } - hir::ExprKind::Array(ref exprs) => { + hir::ExprKind::Array(exprs) => { self.print_expr_vec(exprs); } hir::ExprKind::ConstBlock(ref anon_const) => { self.print_expr_anon_const(anon_const); } - hir::ExprKind::Repeat(ref element, ref count) => { - self.print_expr_repeat(&element, count); + hir::ExprKind::Repeat(element, ref count) => { + self.print_expr_repeat(element, count); } - hir::ExprKind::Struct(ref qpath, fields, ref wth) => { + hir::ExprKind::Struct(qpath, fields, wth) => { self.print_expr_struct(qpath, fields, wth); } - hir::ExprKind::Tup(ref exprs) => { + hir::ExprKind::Tup(exprs) => { self.print_expr_tup(exprs); } - hir::ExprKind::Call(ref func, ref args) => { - self.print_expr_call(&func, args); + hir::ExprKind::Call(func, args) => { + self.print_expr_call(func, args); } - hir::ExprKind::MethodCall(ref segment, ref args, _) => { + hir::ExprKind::MethodCall(segment, args, _) => { self.print_expr_method_call(segment, args); } - hir::ExprKind::Binary(op, ref lhs, ref rhs) => { - self.print_expr_binary(op, &lhs, &rhs); + hir::ExprKind::Binary(op, lhs, rhs) => { + self.print_expr_binary(op, lhs, rhs); } - hir::ExprKind::Unary(op, ref expr) => { - self.print_expr_unary(op, &expr); + hir::ExprKind::Unary(op, expr) => { + self.print_expr_unary(op, expr); } - hir::ExprKind::AddrOf(k, m, ref expr) => { - self.print_expr_addr_of(k, m, &expr); + hir::ExprKind::AddrOf(k, m, expr) => { + self.print_expr_addr_of(k, m, expr); } hir::ExprKind::Lit(ref lit) => { - self.print_literal(&lit); + self.print_literal(lit); } - hir::ExprKind::Cast(ref expr, ref ty) => { + hir::ExprKind::Cast(expr, ty) => { let prec = AssocOp::As.precedence() as i8; - self.print_expr_maybe_paren(&expr, prec); + self.print_expr_maybe_paren(expr, prec); self.space(); self.word_space("as"); - self.print_type(&ty); + self.print_type(ty); } - hir::ExprKind::Type(ref expr, ref ty) => { + hir::ExprKind::Type(expr, ty) => { let prec = AssocOp::Colon.precedence() as i8; - self.print_expr_maybe_paren(&expr, prec); + self.print_expr_maybe_paren(expr, prec); self.word_space(":"); - self.print_type(&ty); + self.print_type(ty); } - hir::ExprKind::DropTemps(ref init) => { + hir::ExprKind::DropTemps(init) => { // Print `{`: self.cbox(INDENT_UNIT); self.ibox(0); @@ -1431,25 +1414,25 @@ impl<'a> State<'a> { // Print `}`: self.bclose_maybe_open(expr.span, true); } - hir::ExprKind::Let(hir::Let { pat, ty, init, .. }) => { - self.print_let(pat, *ty, init); + hir::ExprKind::Let(&hir::Let { pat, ty, init, .. }) => { + self.print_let(pat, ty, init); } - hir::ExprKind::If(ref test, ref blk, ref elseopt) => { - self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e)); + hir::ExprKind::If(test, blk, elseopt) => { + self.print_if(test, blk, elseopt); } - hir::ExprKind::Loop(ref blk, opt_label, _, _) => { + hir::ExprKind::Loop(blk, opt_label, _, _) => { if let Some(label) = opt_label { self.print_ident(label.ident); self.word_space(":"); } self.head("loop"); - self.print_block(&blk); + self.print_block(blk); } - hir::ExprKind::Match(ref expr, arms, _) => { + hir::ExprKind::Match(expr, arms, _) => { self.cbox(INDENT_UNIT); self.ibox(INDENT_UNIT); self.word_nbsp("match"); - self.print_expr_as_cond(&expr); + self.print_expr_as_cond(expr); self.space(); self.bopen(); for arm in arms { @@ -1460,7 +1443,7 @@ impl<'a> State<'a> { hir::ExprKind::Closure { capture_clause, bound_generic_params, - ref fn_decl, + fn_decl, body, fn_decl_span: _, movability: _, @@ -1468,7 +1451,7 @@ impl<'a> State<'a> { self.print_formal_generic_params(bound_generic_params); self.print_capture_clause(capture_clause); - self.print_closure_params(&fn_decl, body); + self.print_closure_params(fn_decl, body); self.space(); // This is a bare expression. @@ -1480,7 +1463,7 @@ impl<'a> State<'a> { // empty box to satisfy the close. self.ibox(0); } - hir::ExprKind::Block(ref blk, opt_label) => { + hir::ExprKind::Block(blk, opt_label) => { if let Some(label) = opt_label { self.print_ident(label.ident); self.word_space(":"); @@ -1489,42 +1472,42 @@ impl<'a> State<'a> { self.cbox(INDENT_UNIT); // head-box, will be closed by print-block after `{` self.ibox(0); - self.print_block(&blk); + self.print_block(blk); } - hir::ExprKind::Assign(ref lhs, ref rhs, _) => { + hir::ExprKind::Assign(lhs, rhs, _) => { let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_maybe_paren(&lhs, prec + 1); + self.print_expr_maybe_paren(lhs, prec + 1); self.space(); self.word_space("="); - self.print_expr_maybe_paren(&rhs, prec); + self.print_expr_maybe_paren(rhs, prec); } - hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { + hir::ExprKind::AssignOp(op, lhs, rhs) => { let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_maybe_paren(&lhs, prec + 1); + self.print_expr_maybe_paren(lhs, prec + 1); self.space(); self.word(op.node.as_str()); self.word_space("="); - self.print_expr_maybe_paren(&rhs, prec); + self.print_expr_maybe_paren(rhs, prec); } - hir::ExprKind::Field(ref expr, ident) => { + hir::ExprKind::Field(expr, ident) => { self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); self.word("."); self.print_ident(ident); } - hir::ExprKind::Index(ref expr, ref index) => { - self.print_expr_maybe_paren(&expr, parser::PREC_POSTFIX); + hir::ExprKind::Index(expr, index) => { + self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); self.word("["); - self.print_expr(&index); + self.print_expr(index); self.word("]"); } hir::ExprKind::Path(ref qpath) => self.print_qpath(qpath, true), - hir::ExprKind::Break(destination, ref opt_expr) => { + hir::ExprKind::Break(destination, opt_expr) => { self.word("break"); if let Some(label) = destination.label { self.space(); self.print_ident(label.ident); } - if let Some(ref expr) = *opt_expr { + if let Some(expr) = opt_expr { self.space(); self.print_expr_maybe_paren(expr, parser::PREC_JUMP); } @@ -1536,20 +1519,20 @@ impl<'a> State<'a> { self.print_ident(label.ident); } } - hir::ExprKind::Ret(ref result) => { + hir::ExprKind::Ret(result) => { self.word("return"); - if let Some(ref expr) = *result { + if let Some(expr) = result { self.word(" "); - self.print_expr_maybe_paren(&expr, parser::PREC_JUMP); + self.print_expr_maybe_paren(expr, parser::PREC_JUMP); } } - hir::ExprKind::InlineAsm(ref asm) => { + hir::ExprKind::InlineAsm(asm) => { self.word("asm!"); self.print_inline_asm(asm); } - hir::ExprKind::Yield(ref expr, _) => { + hir::ExprKind::Yield(expr, _) => { self.word_space("yield"); - self.print_expr_maybe_paren(&expr, parser::PREC_JUMP); + self.print_expr_maybe_paren(expr, parser::PREC_JUMP); } hir::ExprKind::Err => { self.popen(); @@ -1562,10 +1545,10 @@ impl<'a> State<'a> { } pub fn print_local_decl(&mut self, loc: &hir::Local<'_>) { - self.print_pat(&loc.pat); - if let Some(ref ty) = loc.ty { + self.print_pat(loc.pat); + if let Some(ty) = loc.ty { self.word_space(":"); - self.print_type(&ty); + self.print_type(ty); } } @@ -1596,8 +1579,8 @@ impl<'a> State<'a> { pub fn print_qpath(&mut self, qpath: &hir::QPath<'_>, colons_before_params: bool) { match *qpath { - hir::QPath::Resolved(None, ref path) => self.print_path(path, colons_before_params), - hir::QPath::Resolved(Some(ref qself), ref path) => { + hir::QPath::Resolved(None, path) => self.print_path(path, colons_before_params), + hir::QPath::Resolved(Some(qself), path) => { self.word("<"); self.print_type(qself); self.space(); @@ -1627,11 +1610,11 @@ impl<'a> State<'a> { colons_before_params, ) } - hir::QPath::TypeRelative(ref qself, ref item_segment) => { + hir::QPath::TypeRelative(qself, item_segment) => { // If we've got a compound-qualified-path, let's push an additional pair of angle // brackets, so that we pretty-print `<::C>` as `::C`, instead of just // `A::B::C` (since the latter could be ambiguous to the user) - if let hir::TyKind::Path(hir::QPath::Resolved(None, _)) = &qself.kind { + if let hir::TyKind::Path(hir::QPath::Resolved(None, _)) = qself.kind { self.print_type(qself); } else { self.word("<"); @@ -1663,7 +1646,7 @@ impl<'a> State<'a> { ) { if generic_args.parenthesized { self.word("("); - self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(&ty)); + self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(ty)); self.word(")"); self.space_if_not_bol(); @@ -1694,7 +1677,7 @@ impl<'a> State<'a> { start_or_comma(self); self.commasep( Inconsistent, - &generic_args.args, + generic_args.args, |s, generic_arg| match generic_arg { GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt), GenericArg::Lifetime(_) => {} @@ -1712,7 +1695,7 @@ impl<'a> State<'a> { self.word(".."); } - for binding in generic_args.bindings.iter() { + for binding in generic_args.bindings { start_or_comma(self); self.print_type_binding(binding); } @@ -1731,7 +1714,7 @@ impl<'a> State<'a> { hir::TypeBindingKind::Equality { ref term } => { self.word_space("="); match term { - Term::Ty(ref ty) => self.print_type(ty), + Term::Ty(ty) => self.print_type(ty), Term::Const(ref c) => self.print_anon_const(c), } } @@ -1748,7 +1731,7 @@ impl<'a> State<'a> { // is that it doesn't matter match pat.kind { PatKind::Wild => self.word("_"), - PatKind::Binding(binding_mode, _, ident, ref sub) => { + PatKind::Binding(binding_mode, _, ident, sub) => { match binding_mode { hir::BindingAnnotation::Ref => { self.word_nbsp("ref"); @@ -1764,33 +1747,33 @@ impl<'a> State<'a> { } } self.print_ident(ident); - if let Some(ref p) = *sub { + if let Some(p) = sub { self.word("@"); - self.print_pat(&p); + self.print_pat(p); } } - PatKind::TupleStruct(ref qpath, ref elts, ddpos) => { + PatKind::TupleStruct(ref qpath, elts, ddpos) => { self.print_qpath(qpath, true); self.popen(); if let Some(ddpos) = ddpos { - self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p)); + self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p)); if ddpos != 0 { self.word_space(","); } self.word(".."); if ddpos != elts.len() { self.word(","); - self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p)); + self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p)); } } else { - self.commasep(Inconsistent, &elts, |s, p| s.print_pat(&p)); + self.commasep(Inconsistent, elts, |s, p| s.print_pat(p)); } self.pclose(); } PatKind::Path(ref qpath) => { self.print_qpath(qpath, true); } - PatKind::Struct(ref qpath, ref fields, etc) => { + PatKind::Struct(ref qpath, fields, etc) => { self.print_qpath(qpath, true); self.nbsp(); self.word("{"); @@ -1800,14 +1783,14 @@ impl<'a> State<'a> { } self.commasep_cmnt( Consistent, - &fields, + fields, |s, f| { s.cbox(INDENT_UNIT); if !f.is_shorthand { s.print_ident(f.ident); s.word_nbsp(":"); } - s.print_pat(&f.pat); + s.print_pat(f.pat); s.end() }, |f| f.pat.span, @@ -1823,58 +1806,58 @@ impl<'a> State<'a> { } self.word("}"); } - PatKind::Or(ref pats) => { - self.strsep("|", true, Inconsistent, &pats, |s, p| s.print_pat(&p)); + PatKind::Or(pats) => { + self.strsep("|", true, Inconsistent, pats, |s, p| s.print_pat(p)); } - PatKind::Tuple(ref elts, ddpos) => { + PatKind::Tuple(elts, ddpos) => { self.popen(); if let Some(ddpos) = ddpos { - self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p)); + self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p)); if ddpos != 0 { self.word_space(","); } self.word(".."); if ddpos != elts.len() { self.word(","); - self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p)); + self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p)); } } else { - self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p)); + self.commasep(Inconsistent, elts, |s, p| s.print_pat(p)); if elts.len() == 1 { self.word(","); } } self.pclose(); } - PatKind::Box(ref inner) => { + PatKind::Box(inner) => { let is_range_inner = matches!(inner.kind, PatKind::Range(..)); self.word("box "); if is_range_inner { self.popen(); } - self.print_pat(&inner); + self.print_pat(inner); if is_range_inner { self.pclose(); } } - PatKind::Ref(ref inner, mutbl) => { + PatKind::Ref(inner, mutbl) => { let is_range_inner = matches!(inner.kind, PatKind::Range(..)); self.word("&"); self.word(mutbl.prefix_str()); if is_range_inner { self.popen(); } - self.print_pat(&inner); + self.print_pat(inner); if is_range_inner { self.pclose(); } } - PatKind::Lit(ref e) => self.print_expr(&e), - PatKind::Range(ref begin, ref end, ref end_kind) => { + PatKind::Lit(e) => self.print_expr(e), + PatKind::Range(begin, end, end_kind) => { if let Some(expr) = begin { self.print_expr(expr); } - match *end_kind { + match end_kind { RangeEnd::Included => self.word("..."), RangeEnd::Excluded => self.word(".."), } @@ -1882,24 +1865,24 @@ impl<'a> State<'a> { self.print_expr(expr); } } - PatKind::Slice(ref before, ref slice, ref after) => { + PatKind::Slice(before, slice, after) => { self.word("["); - self.commasep(Inconsistent, &before, |s, p| s.print_pat(&p)); - if let Some(ref p) = *slice { + self.commasep(Inconsistent, before, |s, p| s.print_pat(p)); + if let Some(p) = slice { if !before.is_empty() { self.word_space(","); } if let PatKind::Wild = p.kind { // Print nothing. } else { - self.print_pat(&p); + self.print_pat(p); } self.word(".."); if !after.is_empty() { self.word_space(","); } } - self.commasep(Inconsistent, &after, |s, p| s.print_pat(&p)); + self.commasep(Inconsistent, after, |s, p| s.print_pat(p)); self.word("]"); } } @@ -1908,7 +1891,7 @@ impl<'a> State<'a> { pub fn print_param(&mut self, arg: &hir::Param<'_>) { self.print_outer_attributes(self.attrs(arg.hir_id)); - self.print_pat(&arg.pat); + self.print_pat(arg.pat); } pub fn print_arm(&mut self, arm: &hir::Arm<'_>) { @@ -1920,32 +1903,32 @@ impl<'a> State<'a> { self.cbox(INDENT_UNIT); self.ann.pre(self, AnnNode::Arm(arm)); self.ibox(0); - self.print_outer_attributes(&self.attrs(arm.hir_id)); - self.print_pat(&arm.pat); + self.print_outer_attributes(self.attrs(arm.hir_id)); + self.print_pat(arm.pat); self.space(); if let Some(ref g) = arm.guard { - match g { + match *g { hir::Guard::If(e) => { self.word_space("if"); - self.print_expr(&e); + self.print_expr(e); self.space(); } - hir::Guard::IfLet(hir::Let { pat, ty, init, .. }) => { + hir::Guard::IfLet(&hir::Let { pat, ty, init, .. }) => { self.word_nbsp("if"); - self.print_let(pat, *ty, init); + self.print_let(pat, ty, init); } } } self.word_space("=>"); match arm.body.kind { - hir::ExprKind::Block(ref blk, opt_label) => { + hir::ExprKind::Block(blk, opt_label) => { if let Some(label) = opt_label { self.print_ident(label.ident); self.word_space(":"); } // the block will close the pattern's ibox - self.print_block_unclosed(&blk); + self.print_block_unclosed(blk); // If it is a user-provided unsafe block, print a comma after it if let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = blk.rules @@ -1955,7 +1938,7 @@ impl<'a> State<'a> { } _ => { self.end(); // close the ibox for the pattern - self.print_expr(&arm.body); + self.print_expr(arm.body); self.word(","); } } @@ -1978,13 +1961,13 @@ impl<'a> State<'a> { self.nbsp(); self.print_name(name); } - self.print_generic_params(&generics.params); + self.print_generic_params(generics.params); self.popen(); let mut i = 0; // Make sure we aren't supplied *both* `arg_names` and `body_id`. assert!(arg_names.is_empty() || body_id.is_none()); - self.commasep(Inconsistent, &decl.inputs, |s, ty| { + self.commasep(Inconsistent, decl.inputs, |s, ty| { s.ibox(INDENT_UNIT); if let Some(arg_name) = arg_names.get(i) { s.word(arg_name.to_string()); @@ -2011,7 +1994,7 @@ impl<'a> State<'a> { fn print_closure_params(&mut self, decl: &hir::FnDecl<'_>, body_id: hir::BodyId) { self.word("|"); let mut i = 0; - self.commasep(Inconsistent, &decl.inputs, |s, ty| { + self.commasep(Inconsistent, decl.inputs, |s, ty| { s.ibox(INDENT_UNIT); s.ann.nested(s, Nested::BodyParamPat(body_id, i)); @@ -2035,8 +2018,8 @@ impl<'a> State<'a> { self.space_if_not_bol(); self.word_space("->"); match decl.output { - hir::FnRetTy::Return(ref ty) => { - self.print_type(&ty); + hir::FnRetTy::Return(ty) => { + self.print_type(ty); self.maybe_print_comment(ty.span.lo()); } hir::FnRetTy::DefaultReturn(..) => unreachable!(), @@ -2107,20 +2090,20 @@ impl<'a> State<'a> { match param.kind { GenericParamKind::Lifetime { .. } => {} - GenericParamKind::Type { ref default, .. } => { + GenericParamKind::Type { default, .. } => { if let Some(default) = default { self.space(); self.word_space("="); - self.print_type(&default) + self.print_type(default); } } - GenericParamKind::Const { ref ty, ref default } => { + GenericParamKind::Const { ty, ref default } => { self.word_space(":"); self.print_type(ty); - if let Some(ref default) = default { + if let Some(default) = default { self.space(); self.word_space("="); - self.print_anon_const(&default) + self.print_anon_const(default); } } } @@ -2143,7 +2126,7 @@ impl<'a> State<'a> { self.word_space(","); } - match predicate { + match *predicate { hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { bound_generic_params, bounded_ty, @@ -2151,11 +2134,11 @@ impl<'a> State<'a> { .. }) => { self.print_formal_generic_params(bound_generic_params); - self.print_type(&bounded_ty); - self.print_bounds(":", *bounds); + self.print_type(bounded_ty); + self.print_bounds(":", bounds); } hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { - lifetime, + ref lifetime, bounds, .. }) => { @@ -2200,7 +2183,7 @@ impl<'a> State<'a> { pub fn print_mt(&mut self, mt: &hir::MutTy<'_>, print_const: bool) { self.print_mutability(mt.mutbl, print_const); - self.print_type(&mt.ty) + self.print_type(mt.ty); } pub fn print_fn_output(&mut self, decl: &hir::FnDecl<'_>) { @@ -2213,11 +2196,11 @@ impl<'a> State<'a> { self.word_space("->"); match decl.output { hir::FnRetTy::DefaultReturn(..) => unreachable!(), - hir::FnRetTy::Return(ref ty) => self.print_type(&ty), + hir::FnRetTy::Return(ty) => self.print_type(ty), } self.end(); - if let hir::FnRetTy::Return(ref output) = decl.output { + if let hir::FnRetTy::Return(output) = decl.output { self.maybe_print_comment(output.span.lo()); } } @@ -2243,7 +2226,7 @@ impl<'a> State<'a> { asyncness: hir::IsAsync::NotAsync, }, name, - &generics, + generics, arg_names, None, ); @@ -2312,7 +2295,7 @@ fn stmt_ends_with_semi(stmt: &hir::StmtKind<'_>) -> bool { match *stmt { hir::StmtKind::Local(_) => true, hir::StmtKind::Item(_) => false, - hir::StmtKind::Expr(ref e) => expr_requires_semi_to_be_stmt(&e), + hir::StmtKind::Expr(e) => expr_requires_semi_to_be_stmt(e), hir::StmtKind::Semi(..) => false, } } @@ -2351,22 +2334,22 @@ fn contains_exterior_struct_lit(value: &hir::Expr<'_>) -> bool { match value.kind { hir::ExprKind::Struct(..) => true, - hir::ExprKind::Assign(ref lhs, ref rhs, _) - | hir::ExprKind::AssignOp(_, ref lhs, ref rhs) - | hir::ExprKind::Binary(_, ref lhs, ref rhs) => { + hir::ExprKind::Assign(lhs, rhs, _) + | hir::ExprKind::AssignOp(_, lhs, rhs) + | hir::ExprKind::Binary(_, lhs, rhs) => { // `X { y: 1 } + X { y: 2 }` - contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs) + contains_exterior_struct_lit(lhs) || contains_exterior_struct_lit(rhs) } - hir::ExprKind::Unary(_, ref x) - | hir::ExprKind::Cast(ref x, _) - | hir::ExprKind::Type(ref x, _) - | hir::ExprKind::Field(ref x, _) - | hir::ExprKind::Index(ref x, _) => { + hir::ExprKind::Unary(_, x) + | hir::ExprKind::Cast(x, _) + | hir::ExprKind::Type(x, _) + | hir::ExprKind::Field(x, _) + | hir::ExprKind::Index(x, _) => { // `&X { y: 1 }, X { y: 1 }.y` - contains_exterior_struct_lit(&x) + contains_exterior_struct_lit(x) } - hir::ExprKind::MethodCall(.., ref exprs, _) => { + hir::ExprKind::MethodCall(.., exprs, _) => { // `X { y: 1 }.bar(...)` contains_exterior_struct_lit(&exprs[0]) } From 7fc77806d4f66819cf9d7ebd53a3338686c08b7d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 3 Jul 2022 11:29:49 -0400 Subject: [PATCH 07/14] fix interpreter validity check on Box --- .../src/interpret/validity.rs | 34 +++++++++++++++---- compiler/rustc_const_eval/src/lib.rs | 1 + 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 847694cbd10cb..600d25548d4d8 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -594,13 +594,35 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' Ok(true) } ty::Adt(def, ..) if def.is_box() => { - let unique = self.ecx.operand_field(value, 0)?; - let nonnull = self.ecx.operand_field(&unique, 0)?; - let ptr = self.ecx.operand_field(&nonnull, 0)?; - self.check_safe_pointer(&ptr, "box")?; + // Box is special, very special. We carefully assert all the assumptions we make + // here; if this needs to be adjusted, remember to also adjust all the other + // visitors -- in particular the Stacked Borrows retagging visitor in Miri. + // Did I mention that this is a gross hack? Anyway... - // Check other fields of Box - self.walk_value(value)?; + // `Box` has two fields: the pointer we care about, and the allocator. + assert_eq!(value.layout.fields.count(), 2, "`Box` must have exactly 2 fields"); + let (unique_ptr, alloc) = + (self.ecx.operand_field(value, 0)?, self.ecx.operand_field(value, 1)?); + // Unfortunately there is some type junk in the way here: `unique_ptr` is a `Unique`... + // (which means another 2 fields, the second of which is a `PhantomData`) + assert_eq!(unique_ptr.layout.fields.count(), 2); + let (nonnull_ptr, phantom) = ( + self.ecx.operand_field(&unique_ptr, 0)?, + self.ecx.operand_field(&unique_ptr, 1)?, + ); + assert!( + phantom.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_phantom_data()), + "2nd field of `Unique` should be PhantomData but is {:?}", + phantom.layout.ty, + ); + // ... that contains a `NonNull`... (gladly, only a single field here) + assert_eq!(nonnull_ptr.layout.fields.count(), 1); + let raw_ptr = self.ecx.operand_field(&nonnull_ptr, 0)?; // the actual raw ptr + // ... whose only field finally is a raw ptr we can dereference. + self.check_safe_pointer(&raw_ptr, "box")?; + // The second `Box` field is the allocator, which we recursively check for validity + // like in regular structs. + self.walk_value(&alloc)?; Ok(true) } ty::FnPtr(_sig) => { diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 5bf91879066f4..2d42ae236ad9d 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -21,6 +21,7 @@ Rust MIR: a lowered representation of Rust. #![feature(trusted_step)] #![feature(try_blocks)] #![feature(yeet_expr)] +#![feature(is_some_with)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] From d7edf66a5a92f66672bc9e84d58db170b3ea2d9a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 3 Jul 2022 22:55:25 -0400 Subject: [PATCH 08/14] move Box mess handling into general visitor --- .../src/interpret/validity.rs | 40 +++------------ .../rustc_const_eval/src/interpret/visitor.rs | 49 +++++++++++++++++++ 2 files changed, 55 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 600d25548d4d8..0bf78446e37fa 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -593,38 +593,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' self.check_safe_pointer(value, "reference")?; Ok(true) } - ty::Adt(def, ..) if def.is_box() => { - // Box is special, very special. We carefully assert all the assumptions we make - // here; if this needs to be adjusted, remember to also adjust all the other - // visitors -- in particular the Stacked Borrows retagging visitor in Miri. - // Did I mention that this is a gross hack? Anyway... - - // `Box` has two fields: the pointer we care about, and the allocator. - assert_eq!(value.layout.fields.count(), 2, "`Box` must have exactly 2 fields"); - let (unique_ptr, alloc) = - (self.ecx.operand_field(value, 0)?, self.ecx.operand_field(value, 1)?); - // Unfortunately there is some type junk in the way here: `unique_ptr` is a `Unique`... - // (which means another 2 fields, the second of which is a `PhantomData`) - assert_eq!(unique_ptr.layout.fields.count(), 2); - let (nonnull_ptr, phantom) = ( - self.ecx.operand_field(&unique_ptr, 0)?, - self.ecx.operand_field(&unique_ptr, 1)?, - ); - assert!( - phantom.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_phantom_data()), - "2nd field of `Unique` should be PhantomData but is {:?}", - phantom.layout.ty, - ); - // ... that contains a `NonNull`... (gladly, only a single field here) - assert_eq!(nonnull_ptr.layout.fields.count(), 1); - let raw_ptr = self.ecx.operand_field(&nonnull_ptr, 0)?; // the actual raw ptr - // ... whose only field finally is a raw ptr we can dereference. - self.check_safe_pointer(&raw_ptr, "box")?; - // The second `Box` field is the allocator, which we recursively check for validity - // like in regular structs. - self.walk_value(&alloc)?; - Ok(true) - } ty::FnPtr(_sig) => { let value = try_validation!( self.ecx.read_scalar(value).and_then(|v| v.check_init()), @@ -835,6 +803,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> Ok(()) } + #[inline] + fn visit_box(&mut self, op: &OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { + self.check_safe_pointer(op, "box")?; + Ok(()) + } + #[inline] fn visit_value(&mut self, op: &OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { trace!("visit_value: {:?}, {:?}", *op, op.layout); @@ -843,8 +817,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> if self.try_visit_primitive(op)? { return Ok(()); } - // Sanity check: `builtin_deref` does not know any pointers that are not primitive. - assert!(op.layout.ty.builtin_deref(true).is_none()); // Special check preventing `UnsafeCell` in the inner part of constants if let Some(def) = op.layout.ty.ty_adt_def() { diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index 2b77ed8989345..ded4c6a557a40 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -151,6 +151,14 @@ macro_rules! make_value_visitor { { Ok(()) } + /// Visits the given value as the pointer of a `Box`. There is nothing to recurse into. + /// The type of `v` will be a raw pointer, but this is a field of `Box` and the + /// pointee type is the actual `T`. + #[inline(always)] + fn visit_box(&mut self, _v: &Self::V) -> InterpResult<'tcx> + { + Ok(()) + } /// Visits this value as an aggregate, you are getting an iterator yielding /// all the fields (still in an `InterpResult`, you have to do error handling yourself). /// Recurses into the fields. @@ -221,6 +229,47 @@ macro_rules! make_value_visitor { // Slices do not need special handling here: they have `Array` field // placement with length 0, so we enter the `Array` case below which // indirectly uses the metadata to determine the actual length. + + // However, `Box`... let's talk about `Box`. + ty::Adt(def, ..) if def.is_box() => { + // `Box` is a hybrid primitive-library-defined type that one the one hand is + // a dereferenceable pointer, on the other hand has *basically arbitrary + // user-defined layout* since the user controls the 'allocator' field. So it + // cannot be treated like a normal pointer, since it does not fit into an + // `Immediate`. Yeah, it is quite terrible. But many visitors want to do + // something with "all boxed pointers", so we handle this mess for them. + // + // When we hit a `Box`, we do not do the usual `visit_aggregate`; instead, + // we (a) call `visit_box` on the pointer value, and (b) recurse on the + // allocator field. We also assert tons of things to ensure we do not miss + // any other fields. + + // `Box` has two fields: the pointer we care about, and the allocator. + assert_eq!(v.layout().fields.count(), 2, "`Box` must have exactly 2 fields"); + let (unique_ptr, alloc) = + (v.project_field(self.ecx(), 0)?, v.project_field(self.ecx(), 1)?); + // Unfortunately there is some type junk in the way here: `unique_ptr` is a `Unique`... + // (which means another 2 fields, the second of which is a `PhantomData`) + assert_eq!(unique_ptr.layout().fields.count(), 2); + let (nonnull_ptr, phantom) = ( + unique_ptr.project_field(self.ecx(), 0)?, + unique_ptr.project_field(self.ecx(), 1)?, + ); + assert!( + phantom.layout().ty.ty_adt_def().is_some_and(|adt| adt.is_phantom_data()), + "2nd field of `Unique` should be PhantomData but is {:?}", + phantom.layout().ty, + ); + // ... that contains a `NonNull`... (gladly, only a single field here) + assert_eq!(nonnull_ptr.layout().fields.count(), 1); + let raw_ptr = nonnull_ptr.project_field(self.ecx(), 0)?; // the actual raw ptr + // ... whose only field finally is a raw ptr we can dereference. + self.visit_box(&raw_ptr)?; + + // The second `Box` field is the allocator, which we recursively check for validity + // like in regular structs. + self.visit_field(v, 1, &alloc)?; + } _ => {}, }; From eb80407d79a25cb9bdd98eca47764e57114d1d86 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Mon, 4 Jul 2022 20:46:59 +0900 Subject: [PATCH 09/14] suggest `#[derive(Default)]` to enums with `#[default]` --- compiler/rustc_resolve/src/diagnostics.rs | 9 +++++++++ src/test/ui/enum/suggest-default-attribute.rs | 8 ++++++++ src/test/ui/enum/suggest-default-attribute.stderr | 14 ++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 src/test/ui/enum/suggest-default-attribute.rs create mode 100644 src/test/ui/enum/suggest-default-attribute.stderr diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index e8b7cee573490..4fbbd9deaebb4 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1495,6 +1495,15 @@ impl<'a> Resolver<'a> { err.help("have you added the `#[macro_use]` on the module/import?"); return; } + if ident.name == kw::Default + && let ModuleKind::Def(DefKind::Enum, def_id, _) = parent_scope.module.kind + && let Some(span) = self.opt_span(def_id) + { + err.span_help( + self.session.source_map().guess_head_span(span), + "consider adding `#[derive(Default)]` to this enum", + ); + } for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] { if let Ok(binding) = self.early_resolve_ident_in_lexical_scope( ident, diff --git a/src/test/ui/enum/suggest-default-attribute.rs b/src/test/ui/enum/suggest-default-attribute.rs new file mode 100644 index 0000000000000..33bd0d2408139 --- /dev/null +++ b/src/test/ui/enum/suggest-default-attribute.rs @@ -0,0 +1,8 @@ +pub enum Test { //~ HELP consider adding `#[derive(Default)]` to this enum + #[default] + //~^ ERROR cannot find attribute `default` in this scope + First, + Second, +} + +fn main() {} diff --git a/src/test/ui/enum/suggest-default-attribute.stderr b/src/test/ui/enum/suggest-default-attribute.stderr new file mode 100644 index 0000000000000..791f219e8f95f --- /dev/null +++ b/src/test/ui/enum/suggest-default-attribute.stderr @@ -0,0 +1,14 @@ +error: cannot find attribute `default` in this scope + --> $DIR/suggest-default-attribute.rs:2:7 + | +LL | #[default] + | ^^^^^^^ + | +help: consider adding `#[derive(Default)]` to this enum + --> $DIR/suggest-default-attribute.rs:1:1 + | +LL | pub enum Test { + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + From c2ed08715b2f6b946089ccf967d18e70bb04ea39 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 1 Jul 2022 13:36:49 +0200 Subject: [PATCH 10/14] remove unused function argument --- .../infer/error_reporting/need_type_info.rs | 2 -- .../src/traits/error_reporting/mod.rs | 27 +++---------------- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 11 ++------ compiler/rustc_typeck/src/check/writeback.rs | 2 -- 4 files changed, 5 insertions(+), 37 deletions(-) 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 07dcf3876c806..33ce43cd5593b 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 @@ -315,8 +315,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { body_id: Option, failure_span: Span, arg: GenericArg<'tcx>, - // FIXME(#94483): Either use this or remove it. - _impl_candidates: Vec>, error_code: TypeAnnotationNeeded, should_label_span: bool, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { 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 fa56219b409d1..88b09f4de0a4c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1980,7 +1980,6 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { body_id, span, trait_ref.self_ty().skip_binder().into(), - vec![], ErrorCode::E0282, false, ) @@ -2005,19 +2004,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { let subst = data.trait_ref.substs.iter().find(|s| s.has_infer_types_or_consts()); let mut err = if let Some(subst) = subst { - let impl_candidates = self - .find_similar_impl_candidates(trait_ref) - .into_iter() - .map(|candidate| candidate.trait_ref) - .collect(); - self.emit_inference_failure_err( - body_id, - span, - subst, - impl_candidates, - ErrorCode::E0283, - true, - ) + self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0283, true) } else { struct_span_err!( self.tcx.sess, @@ -2117,7 +2104,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { return; } - self.emit_inference_failure_err(body_id, span, arg, vec![], ErrorCode::E0282, false) + self.emit_inference_failure_err(body_id, span, arg, ErrorCode::E0282, false) } ty::PredicateKind::Subtype(data) => { @@ -2131,14 +2118,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { let SubtypePredicate { a_is_expected: _, a, b } = data; // both must be type variables, or the other would've been instantiated assert!(a.is_ty_var() && b.is_ty_var()); - self.emit_inference_failure_err( - body_id, - span, - a.into(), - vec![], - ErrorCode::E0282, - true, - ) + self.emit_inference_failure_err(body_id, span, a.into(), ErrorCode::E0282, true) } ty::PredicateKind::Projection(data) => { if predicate.references_error() || self.is_tainted_by_errors() { @@ -2155,7 +2135,6 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { body_id, span, subst, - vec![], ErrorCode::E0284, true, ); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index bce2e85de845d..5297c48b4c37d 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1538,15 +1538,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } else { if !self.is_tainted_by_errors() { - self.emit_inference_failure_err( - (**self).body_id, - sp, - ty.into(), - vec![], - E0282, - true, - ) - .emit(); + self.emit_inference_failure_err((**self).body_id, sp, ty.into(), E0282, true) + .emit(); } let err = self.tcx.ty_error(); self.demand_suptype(sp, err, ty); diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 67160b98b9dc0..16e5639096c5e 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -692,7 +692,6 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { Some(self.body.id()), self.span.to_span(self.tcx), t.into(), - vec![], E0282, false, ) @@ -707,7 +706,6 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { Some(self.body.id()), self.span.to_span(self.tcx), c.into(), - vec![], E0282, false, ) From f1836c453a34bf7904508146598568dc47dcffea Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 1 Jul 2022 14:09:33 +0200 Subject: [PATCH 11/14] update infer cost computation for types --- .../infer/error_reporting/need_type_info.rs | 62 ++++++++++++------- .../ui/inference/need_type_info/channel.rs | 19 ++++++ .../inference/need_type_info/channel.stderr | 25 ++++++++ src/test/ui/issues/issue-25368.rs | 4 +- src/test/ui/issues/issue-25368.stderr | 14 ++--- ...cannot_infer_local_or_vec_in_tuples.stderr | 14 +++-- 6 files changed, 101 insertions(+), 37 deletions(-) create mode 100644 src/test/ui/inference/need_type_info/channel.rs create mode 100644 src/test/ui/inference/need_type_info/channel.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 33ce43cd5593b..f8ee006b9c89a 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 @@ -602,41 +602,58 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { /// Sources with a small cost are prefer and should result /// in a clearer and idiomatic suggestion. fn source_cost(&self, source: &InferSource<'tcx>) -> usize { - let tcx = self.infcx.tcx; - - fn arg_cost<'tcx>(arg: GenericArg<'tcx>) -> usize { - match arg.unpack() { - GenericArgKind::Lifetime(_) => 0, // erased - GenericArgKind::Type(ty) => ty_cost(ty), - GenericArgKind::Const(_) => 3, // some non-zero value - } + #[derive(Clone, Copy)] + struct CostCtxt<'tcx> { + tcx: TyCtxt<'tcx>, } - fn ty_cost<'tcx>(ty: Ty<'tcx>) -> usize { - match ty.kind() { - ty::Closure(..) => 100, - ty::FnDef(..) => 20, - ty::FnPtr(..) => 10, - ty::Infer(..) => 0, - _ => 1, + impl<'tcx> CostCtxt<'tcx> { + fn arg_cost(self, arg: GenericArg<'tcx>) -> usize { + match arg.unpack() { + GenericArgKind::Lifetime(_) => 0, // erased + GenericArgKind::Type(ty) => self.ty_cost(ty), + GenericArgKind::Const(_) => 3, // some non-zero value + } + } + fn ty_cost(self, ty: Ty<'tcx>) -> usize { + match ty.kind() { + ty::Closure(..) => 1000, + ty::FnDef(..) => 150, + ty::FnPtr(..) => 30, + ty::Adt(def, substs) => { + 5 + self + .tcx + .generics_of(def.did()) + .own_substs_no_defaults(self.tcx, substs) + .iter() + .map(|&arg| self.arg_cost(arg)) + .sum::() + } + ty::Tuple(args) => 5 + args.iter().map(|arg| self.ty_cost(arg)).sum::(), + ty::Infer(..) => 0, + _ => 1, + } } } // The sources are listed in order of preference here. + let tcx = self.infcx.tcx; + let ctx = CostCtxt { tcx }; match source.kind { - InferSourceKind::LetBinding { ty, .. } => ty_cost(ty), - InferSourceKind::ClosureArg { ty, .. } => 5 + ty_cost(ty), + InferSourceKind::LetBinding { ty, .. } => ctx.ty_cost(ty), + InferSourceKind::ClosureArg { ty, .. } => ctx.ty_cost(ty), InferSourceKind::GenericArg { def_id, generic_args, .. } => { let variant_cost = match tcx.def_kind(def_id) { - DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15, // `None::` and friends are ugly. - _ => 12, + // `None::` and friends are ugly. + DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15, + _ => 10, }; - variant_cost + generic_args.iter().map(|&arg| arg_cost(arg)).sum::() + variant_cost + generic_args.iter().map(|&arg| ctx.arg_cost(arg)).sum::() } InferSourceKind::FullyQualifiedMethodCall { substs, .. } => { - 20 + substs.iter().map(|arg| arg_cost(arg)).sum::() + 20 + substs.iter().map(|arg| ctx.arg_cost(arg)).sum::() } InferSourceKind::ClosureReturn { ty, should_wrap_expr, .. } => { - 30 + ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 } + 30 + ctx.ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 } } } } @@ -646,6 +663,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn update_infer_source(&mut self, new_source: InferSource<'tcx>) { let cost = self.source_cost(&new_source) + self.attempt; + debug!(?cost); self.attempt += 1; if cost < self.infer_source_cost { self.infer_source_cost = cost; diff --git a/src/test/ui/inference/need_type_info/channel.rs b/src/test/ui/inference/need_type_info/channel.rs new file mode 100644 index 0000000000000..e2ba5a9417138 --- /dev/null +++ b/src/test/ui/inference/need_type_info/channel.rs @@ -0,0 +1,19 @@ +// Test that we suggest specifying the generic argument of `channel` +// instead of the return type of that function, which is a lot more +// complex. +use std::sync::mpsc::channel; + +fn no_tuple() { + let _data = + channel(); //~ ERROR type annotations needed +} + +fn tuple() { + let (_sender, _receiver) = + channel(); //~ ERROR type annotations needed +} + +fn main() { + no_tuple(); + tuple(); +} diff --git a/src/test/ui/inference/need_type_info/channel.stderr b/src/test/ui/inference/need_type_info/channel.stderr new file mode 100644 index 0000000000000..e33ace0338d50 --- /dev/null +++ b/src/test/ui/inference/need_type_info/channel.stderr @@ -0,0 +1,25 @@ +error[E0282]: type annotations needed + --> $DIR/channel.rs:8:9 + | +LL | channel(); + | ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `channel` + | +help: consider specifying the generic argument + | +LL | channel::(); + | +++++ + +error[E0282]: type annotations needed + --> $DIR/channel.rs:13:9 + | +LL | channel(); + | ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `channel` + | +help: consider specifying the generic argument + | +LL | channel::(); + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/issues/issue-25368.rs b/src/test/ui/issues/issue-25368.rs index b7f0f613e8091..4be83457f7a8b 100644 --- a/src/test/ui/issues/issue-25368.rs +++ b/src/test/ui/issues/issue-25368.rs @@ -5,10 +5,10 @@ use std::marker::PhantomData; struct Foo {foo: PhantomData} fn main() { - let (tx, rx) = //~ ERROR type annotations needed + let (tx, rx) = channel(); - // FIXME(#89862): Suggest adding a generic argument to `channel` instead spawn(move || { tx.send(Foo{ foo: PhantomData }); + //~^ ERROR type annotations needed }); } diff --git a/src/test/ui/issues/issue-25368.stderr b/src/test/ui/issues/issue-25368.stderr index ffcb73849527f..e6ed3aac71032 100644 --- a/src/test/ui/issues/issue-25368.stderr +++ b/src/test/ui/issues/issue-25368.stderr @@ -1,13 +1,13 @@ -error[E0282]: type annotations needed for `(Sender>, std::sync::mpsc::Receiver>)` - --> $DIR/issue-25368.rs:8:9 +error[E0282]: type annotations needed + --> $DIR/issue-25368.rs:11:27 | -LL | let (tx, rx) = - | ^^^^^^^^ +LL | tx.send(Foo{ foo: PhantomData }); + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `PhantomData` | -help: consider giving this pattern a type, where the type for type parameter `T` is specified +help: consider specifying the generic argument | -LL | let (tx, rx): (Sender>, std::sync::mpsc::Receiver>) = - | +++++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | tx.send(Foo{ foo: PhantomData:: }); + | +++++ error: aborting due to previous error diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr index be60cda68b9f0..00f8a747c7122 100644 --- a/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr +++ b/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr @@ -1,13 +1,15 @@ -error[E0282]: type annotations needed for `(Vec,)` - --> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:9 +error[E0282]: type annotations needed + --> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:18 | LL | let (x, ) = (vec![], ); - | ^^^^^ + | ^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Vec` | -help: consider giving this pattern a type, where the type for type parameter `T` is specified + = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider specifying the generic argument + --> $SRC_DIR/alloc/src/macros.rs:LL:COL | -LL | let (x, ): (Vec,) = (vec![], ); - | +++++++++++ +LL | $crate::__rust_force_expr!($crate::vec::Vec::::new()) + | +++++ error: aborting due to previous error From eef34a648b9471658ee08101bc65a6a299e12f1c Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 1 Jul 2022 14:34:00 +0200 Subject: [PATCH 12/14] stop suggesting things inside of macros --- .../infer/error_reporting/need_type_info.rs | 25 +++++++++++++++++-- ...cannot_infer_local_or_vec_in_tuples.stderr | 14 +++++------ 2 files changed, 29 insertions(+), 10 deletions(-) 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 f8ee006b9c89a..c44e53af5b3c2 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 @@ -532,6 +532,22 @@ enum InferSourceKind<'tcx> { }, } +impl<'tcx> InferSource<'tcx> { + /// Returns the span where we're going to insert our suggestion. + /// + /// Used when computing the cost of this infer source to check whether + /// we're inside of a macro expansion. + fn main_insert_span(&self) -> Span { + match self.kind { + InferSourceKind::LetBinding { insert_span, .. } => insert_span, + InferSourceKind::ClosureArg { insert_span, .. } => insert_span, + InferSourceKind::GenericArg { insert_span, .. } => insert_span, + InferSourceKind::FullyQualifiedMethodCall { receiver, .. } => receiver.span, + InferSourceKind::ClosureReturn { data, .. } => data.span(), + } + } +} + impl<'tcx> InferSourceKind<'tcx> { fn ty_msg(&self, infcx: &InferCtxt<'_, 'tcx>) -> String { match *self { @@ -638,7 +654,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { // The sources are listed in order of preference here. let tcx = self.infcx.tcx; let ctx = CostCtxt { tcx }; - match source.kind { + let base_cost = match source.kind { InferSourceKind::LetBinding { ty, .. } => ctx.ty_cost(ty), InferSourceKind::ClosureArg { ty, .. } => ctx.ty_cost(ty), InferSourceKind::GenericArg { def_id, generic_args, .. } => { @@ -655,7 +671,12 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { InferSourceKind::ClosureReturn { ty, should_wrap_expr, .. } => { 30 + ctx.ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 } } - } + }; + + let suggestion_may_apply = + if source.main_insert_span().can_be_used_for_suggestions() { 0 } else { 10000 }; + + base_cost + suggestion_may_apply } /// Uses `fn source_cost` to determine whether this inference source is preferable to diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr index 00f8a747c7122..be60cda68b9f0 100644 --- a/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr +++ b/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr @@ -1,15 +1,13 @@ -error[E0282]: type annotations needed - --> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:18 +error[E0282]: type annotations needed for `(Vec,)` + --> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:9 | LL | let (x, ) = (vec![], ); - | ^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Vec` + | ^^^^^ | - = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider specifying the generic argument - --> $SRC_DIR/alloc/src/macros.rs:LL:COL +help: consider giving this pattern a type, where the type for type parameter `T` is specified | -LL | $crate::__rust_force_expr!($crate::vec::Vec::::new()) - | +++++ +LL | let (x, ): (Vec,) = (vec![], ); + | +++++++++++ error: aborting due to previous error From 7952d2ed8338796aa9b5f0da5a37c7dd8e936182 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 1 Jul 2022 15:20:38 +0200 Subject: [PATCH 13/14] resolve vars in node substs --- .../src/infer/error_reporting/need_type_info.rs | 11 ++++++++--- src/test/ui/inference/ambiguous_type_parameter.stderr | 7 ++++++- .../method-ambig-one-trait-unknown-int-type.stderr | 6 +++++- 3 files changed, 19 insertions(+), 5 deletions(-) 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 c44e53af5b3c2..036692c43dc85 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 @@ -692,6 +692,11 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { } } + fn node_substs_opt(&self, hir_id: HirId) -> Option> { + let substs = self.typeck_results.node_substs_opt(hir_id); + self.infcx.resolve_vars_if_possible(substs) + } + fn opt_node_type(&self, hir_id: HirId) -> Option> { let ty = self.typeck_results.node_type_opt(hir_id); self.infcx.resolve_vars_if_possible(ty) @@ -774,7 +779,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { let tcx = self.infcx.tcx; match expr.kind { hir::ExprKind::Path(ref path) => { - if let Some(substs) = self.typeck_results.node_substs_opt(expr.hir_id) { + if let Some(substs) = self.node_substs_opt(expr.hir_id) { return self.path_inferred_subst_iter(expr.hir_id, substs, path); } } @@ -802,7 +807,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { if generics.has_impl_trait() { None? } - let substs = self.typeck_results.node_substs_opt(expr.hir_id)?; + let substs = self.node_substs_opt(expr.hir_id)?; let span = tcx.hir().span(segment.hir_id?); let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi()); InsertableGenericArgs { @@ -1074,7 +1079,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { .any(|generics| generics.has_impl_trait()) }; if let ExprKind::MethodCall(path, args, span) = expr.kind - && let Some(substs) = self.typeck_results.node_substs_opt(expr.hir_id) + && let Some(substs) = self.node_substs_opt(expr.hir_id) && substs.iter().any(|arg| self.generic_arg_contains_target(arg)) && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) && self.infcx.tcx.trait_of_item(def_id).is_some() diff --git a/src/test/ui/inference/ambiguous_type_parameter.stderr b/src/test/ui/inference/ambiguous_type_parameter.stderr index a08342371b3b5..9cbe221de1393 100644 --- a/src/test/ui/inference/ambiguous_type_parameter.stderr +++ b/src/test/ui/inference/ambiguous_type_parameter.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed --> $DIR/ambiguous_type_parameter.rs:16:19 | LL | InMemoryStore.get_raw(&String::default()); - | ^^^^^^^ cannot infer type for type parameter `K` + | ^^^^^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | >>::get_raw(&InMemoryStore, &String::default()); + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ~ error: aborting due to previous error diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr index 66e7ada3ac5fd..e0f8a5447b081 100644 --- a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr +++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr @@ -13,7 +13,7 @@ error[E0283]: type annotations needed --> $DIR/method-ambig-one-trait-unknown-int-type.rs:26:7 | LL | x.foo(); - | ^^^ cannot infer type for struct `Vec<_>` + | ^^^ | note: multiple `impl`s satisfying `Vec<_>: Foo` found --> $DIR/method-ambig-one-trait-unknown-int-type.rs:9:1 @@ -23,6 +23,10 @@ LL | impl Foo for Vec { ... LL | impl Foo for Vec { | ^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | as Foo>::foo(&x); + | ++++++++++++++++++++++ ~ error[E0308]: mismatched types --> $DIR/method-ambig-one-trait-unknown-int-type.rs:33:20 From f475e880a4c6b2359ebaef88c844daede9c88fc9 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 1 Jul 2022 15:49:05 +0200 Subject: [PATCH 14/14] `InferSource::GenericArg`, check for contains --- .../infer/error_reporting/need_type_info.rs | 37 ++++++++++--------- .../cannot-infer-partial-try-return.rs | 2 +- .../cannot-infer-partial-try-return.stderr | 15 ++++---- src/test/ui/issues/issue-23041.stderr | 9 ++++- src/test/ui/issues/issue-24013.stderr | 9 ++++- 5 files changed, 42 insertions(+), 30 deletions(-) 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 036692c43dc85..4d29fc469462c 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 @@ -533,18 +533,19 @@ enum InferSourceKind<'tcx> { } impl<'tcx> InferSource<'tcx> { - /// Returns the span where we're going to insert our suggestion. - /// - /// Used when computing the cost of this infer source to check whether - /// we're inside of a macro expansion. - fn main_insert_span(&self) -> Span { - match self.kind { - InferSourceKind::LetBinding { insert_span, .. } => insert_span, - InferSourceKind::ClosureArg { insert_span, .. } => insert_span, - InferSourceKind::GenericArg { insert_span, .. } => insert_span, - InferSourceKind::FullyQualifiedMethodCall { receiver, .. } => receiver.span, - InferSourceKind::ClosureReturn { data, .. } => data.span(), - } + fn from_expansion(&self) -> bool { + let source_from_expansion = match self.kind { + InferSourceKind::LetBinding { insert_span, .. } + | InferSourceKind::ClosureArg { insert_span, .. } + | InferSourceKind::GenericArg { insert_span, .. } => insert_span.from_expansion(), + InferSourceKind::FullyQualifiedMethodCall { receiver, .. } => { + receiver.span.from_expansion() + } + InferSourceKind::ClosureReturn { data, should_wrap_expr, .. } => { + data.span().from_expansion() || should_wrap_expr.map_or(false, Span::from_expansion) + } + }; + source_from_expansion || self.span.from_expansion() } } @@ -631,7 +632,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { } } fn ty_cost(self, ty: Ty<'tcx>) -> usize { - match ty.kind() { + match *ty.kind() { ty::Closure(..) => 1000, ty::FnDef(..) => 150, ty::FnPtr(..) => 30, @@ -645,6 +646,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { .sum::() } ty::Tuple(args) => 5 + args.iter().map(|arg| self.ty_cost(arg)).sum::(), + ty::Ref(_, ty, _) => 2 + self.ty_cost(ty), ty::Infer(..) => 0, _ => 1, } @@ -673,8 +675,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { } }; - let suggestion_may_apply = - if source.main_insert_span().can_be_used_for_suggestions() { 0 } else { 10000 }; + let suggestion_may_apply = if source.from_expansion() { 10000 } else { 0 }; base_cost + suggestion_may_apply } @@ -1022,8 +1023,10 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { debug!(?args); let InsertableGenericArgs { insert_span, substs, generics_def_id, def_id } = args; let generics = tcx.generics_of(generics_def_id); - if let Some(argument_index) = - generics.own_substs(substs).iter().position(|&arg| self.generic_arg_is_target(arg)) + if let Some(argument_index) = generics + .own_substs(substs) + .iter() + .position(|&arg| self.generic_arg_contains_target(arg)) { let substs = self.infcx.resolve_vars_if_possible(substs); let generic_args = &generics.own_substs_no_defaults(tcx, substs) diff --git a/src/test/ui/inference/cannot-infer-partial-try-return.rs b/src/test/ui/inference/cannot-infer-partial-try-return.rs index 976827a447860..b555697dc3461 100644 --- a/src/test/ui/inference/cannot-infer-partial-try-return.rs +++ b/src/test/ui/inference/cannot-infer-partial-try-return.rs @@ -16,8 +16,8 @@ fn infallible() -> Result<(), std::convert::Infallible> { fn main() { let x = || -> Result<_, QualifiedError<_>> { - //~^ ERROR type annotations needed for `Result<(), QualifiedError<_>>` infallible()?; Ok(()) + //~^ ERROR type annotations needed }; } diff --git a/src/test/ui/inference/cannot-infer-partial-try-return.stderr b/src/test/ui/inference/cannot-infer-partial-try-return.stderr index c1e43f0b721f5..2a56aaa44fef2 100644 --- a/src/test/ui/inference/cannot-infer-partial-try-return.stderr +++ b/src/test/ui/inference/cannot-infer-partial-try-return.stderr @@ -1,16 +1,15 @@ -error[E0282]: type annotations needed for `Result<(), QualifiedError<_>>` - --> $DIR/cannot-infer-partial-try-return.rs:18:13 +error[E0282]: type annotations needed + --> $DIR/cannot-infer-partial-try-return.rs:20:9 | -LL | let x = || -> Result<_, QualifiedError<_>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | LL | infallible()?; | ------------- type must be known at this point +LL | Ok(()) + | ^^ cannot infer type of the type parameter `E` declared on the enum `Result` | -help: try giving this closure an explicit return type +help: consider specifying the generic arguments | -LL | let x = || -> Result<(), QualifiedError<_>> { - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | Ok::<(), QualifiedError<_>>(()) + | +++++++++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23041.stderr b/src/test/ui/issues/issue-23041.stderr index 401086b204435..7b9a1634a0d4c 100644 --- a/src/test/ui/issues/issue-23041.stderr +++ b/src/test/ui/issues/issue-23041.stderr @@ -1,8 +1,13 @@ error[E0282]: type annotations needed - --> $DIR/issue-23041.rs:6:22 + --> $DIR/issue-23041.rs:6:7 | LL | b.downcast_ref::_>(); - | ^^^^^^^^ cannot infer type + | ^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the associated function `downcast_ref` + | +help: consider specifying the generic arguments + | +LL | b.downcast_ref:: _>(); + | ~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-24013.stderr b/src/test/ui/issues/issue-24013.stderr index 4e3cb88297d3b..863993f450904 100644 --- a/src/test/ui/issues/issue-24013.stderr +++ b/src/test/ui/issues/issue-24013.stderr @@ -1,8 +1,13 @@ error[E0282]: type annotations needed - --> $DIR/issue-24013.rs:5:20 + --> $DIR/issue-24013.rs:5:13 | LL | unsafe {swap::<&mut _>(transmute(&a), transmute(&b))}; - | ^^^^^^ cannot infer type + | ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `swap` + | +help: consider specifying the generic arguments + | +LL | unsafe {swap::<&mut _>(transmute(&a), transmute(&b))}; + | ~~~~~~~~~~ error: aborting due to previous error