From 6f6620b966ce9ea37d034fa9d184d60b84a9ce02 Mon Sep 17 00:00:00 2001 From: Eden Date: Sun, 7 Jun 2020 11:23:15 +0400 Subject: [PATCH 01/45] Rename "cyclone" to "apple-a7" per changes in upstream LLVM See: https://reviews.llvm.org/D70779 https://reviews.llvm.org/D70779#C1703593NL568 LLVM 10 merged into master at: https://github.com/rust-lang/rust/pull/67759 --- src/librustc_target/spec/aarch64_apple_ios.rs | 2 +- src/librustc_target/spec/aarch64_apple_tvos.rs | 2 +- src/librustc_target/spec/apple_sdk_base.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_target/spec/aarch64_apple_ios.rs b/src/librustc_target/spec/aarch64_apple_ios.rs index eac2c3e6aa40c..1447716ca8484 100644 --- a/src/librustc_target/spec/aarch64_apple_ios.rs +++ b/src/librustc_target/spec/aarch64_apple_ios.rs @@ -15,7 +15,7 @@ pub fn target() -> TargetResult { target_vendor: "apple".to_string(), linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { - features: "+neon,+fp-armv8,+cyclone".to_string(), + features: "+neon,+fp-armv8,+apple-a7".to_string(), eliminate_frame_pointer: false, max_atomic_width: Some(128), abi_blacklist: super::arm_base::abi_blacklist(), diff --git a/src/librustc_target/spec/aarch64_apple_tvos.rs b/src/librustc_target/spec/aarch64_apple_tvos.rs index f1cd14ffd11a6..21f660ac8b839 100644 --- a/src/librustc_target/spec/aarch64_apple_tvos.rs +++ b/src/librustc_target/spec/aarch64_apple_tvos.rs @@ -15,7 +15,7 @@ pub fn target() -> TargetResult { target_vendor: "apple".to_string(), linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { - features: "+neon,+fp-armv8,+cyclone".to_string(), + features: "+neon,+fp-armv8,+apple-a7".to_string(), eliminate_frame_pointer: false, max_atomic_width: Some(128), abi_blacklist: super::arm_base::abi_blacklist(), diff --git a/src/librustc_target/spec/apple_sdk_base.rs b/src/librustc_target/spec/apple_sdk_base.rs index c7cff17b1544c..b07c2aef1caca 100644 --- a/src/librustc_target/spec/apple_sdk_base.rs +++ b/src/librustc_target/spec/apple_sdk_base.rs @@ -122,7 +122,7 @@ fn target_cpu(arch: Arch) -> String { match arch { Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher Armv7s => "cortex-a9", - Arm64 => "cyclone", + Arm64 => "apple-a7", I386 => "yonah", X86_64 => "core2", X86_64_macabi => "core2", From 95c4899e55e7aab68f06e67660257d73e6a46eda Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Sun, 7 Jun 2020 23:36:07 +0200 Subject: [PATCH 02/45] Added an example where explicitly dropping a lock is necessary/a good idea. --- src/libstd/sync/mutex.rs | 61 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 797b22fdd1279..6077e1a402965 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -107,6 +107,67 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// /// *guard += 1; /// ``` +/// +/// It is sometimes a good idea (or even necessary) to manually drop the mutex +/// to unlock it as soon as possible. If you need the resource until the end of +/// the scope, this is not needed. +/// +/// ``` +/// use std::sync::{Arc, Mutex}; +/// use std::thread; +/// +/// const N: usize = 3; +/// +/// // Some data to work with in multiple threads. +/// let data_mutex = Arc::new(Mutex::new([1, 2, 3, 4])); +/// // The result of all the work across all threads. +/// let res_mutex = Arc::new(Mutex::new(0)); +/// +/// // Threads other than the main thread. +/// let mut threads = Vec::with_capacity(N); +/// (0..N).for_each(|_| { +/// // Getting clones for the mutexes. +/// let data_mutex_clone = Arc::clone(&data_mutex); +/// let res_mutex_clone = Arc::clone(&res_mutex); +/// +/// threads.push(thread::spawn(move || { +/// let data = *data_mutex_clone.lock().unwrap(); +/// // This is the result of some important and long-ish work. +/// let result = data.iter().fold(0, |acc, x| acc + x * 2); +/// // We drop the `data` explicitely because it's not necessary anymore +/// // and the thread still has work to do. This allow other threads to +/// // start working on the data immediately, without waiting +/// // for the rest of the unrelated work to be done here. +/// std::mem::drop(data); +/// *res_mutex_clone.lock().unwrap() += result; +/// })); +/// }); +/// +/// let data = *data_mutex.lock().unwrap(); +/// // This is the result of some important and long-ish work. +/// let result = data.iter().fold(0, |acc, x| acc + x * 2); +/// // We drop the `data` explicitely because it's not necessary anymore +/// // and the thread still has work to do. This allow other threads to +/// // start working on the data immediately, without waiting +/// // for the rest of the unrelated work to be done here. +/// // +/// // It's even more important here because we `.join` the threads after that. +/// // If we had not dropped the lock, a thread could be waiting forever for +/// // it, causing a deadlock. +/// std::mem::drop(data); +/// // Here the lock is not assigned to a variable and so, even if the scope +/// // does not end after this line, the mutex is still released: +/// // there is no deadlock. +/// *res_mutex.lock().unwrap() += result; +/// +/// threads.into_iter().for_each(|thread| { +/// thread +/// .join() +/// .expect("The thread creating or execution failed !") +/// }); +/// +/// assert_eq!(*res_mutex.lock().unwrap(), 80); +/// ``` #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "mutex_type")] pub struct Mutex { From 9c8f881ccd050f06387612e4b8aa18111c51a63b Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Sun, 7 Jun 2020 23:42:55 +0200 Subject: [PATCH 03/45] Improved the example to work with mutable data, providing a reason for the mutex holding it --- src/libstd/sync/mutex.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 6077e1a402965..633496154aefe 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -119,7 +119,7 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// const N: usize = 3; /// /// // Some data to work with in multiple threads. -/// let data_mutex = Arc::new(Mutex::new([1, 2, 3, 4])); +/// let data_mutex = Arc::new(Mutex::new(vec![1, 2, 3, 4])); /// // The result of all the work across all threads. /// let res_mutex = Arc::new(Mutex::new(0)); /// @@ -131,9 +131,10 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// let res_mutex_clone = Arc::clone(&res_mutex); /// /// threads.push(thread::spawn(move || { -/// let data = *data_mutex_clone.lock().unwrap(); +/// let mut data = data_mutex_clone.lock().unwrap(); /// // This is the result of some important and long-ish work. /// let result = data.iter().fold(0, |acc, x| acc + x * 2); +/// data.push(result); /// // We drop the `data` explicitely because it's not necessary anymore /// // and the thread still has work to do. This allow other threads to /// // start working on the data immediately, without waiting @@ -143,9 +144,10 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// })); /// }); /// -/// let data = *data_mutex.lock().unwrap(); +/// let mut data = data_mutex.lock().unwrap(); /// // This is the result of some important and long-ish work. /// let result = data.iter().fold(0, |acc, x| acc + x * 2); +/// data.push(result); /// // We drop the `data` explicitely because it's not necessary anymore /// // and the thread still has work to do. This allow other threads to /// // start working on the data immediately, without waiting @@ -166,7 +168,7 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// .expect("The thread creating or execution failed !") /// }); /// -/// assert_eq!(*res_mutex.lock().unwrap(), 80); +/// assert_eq!(*res_mutex.lock().unwrap(), 800); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "mutex_type")] From fdef1a5915332a3f9012b41f4176cf2a16025257 Mon Sep 17 00:00:00 2001 From: Poliorcetics Date: Mon, 8 Jun 2020 16:29:47 +0200 Subject: [PATCH 04/45] Simply use drop instead of std::mem::drop Co-authored-by: LeSeulArtichaut --- src/libstd/sync/mutex.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 633496154aefe..c2c86fae654cf 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -139,7 +139,7 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// // and the thread still has work to do. This allow other threads to /// // start working on the data immediately, without waiting /// // for the rest of the unrelated work to be done here. -/// std::mem::drop(data); +/// drop(data); /// *res_mutex_clone.lock().unwrap() += result; /// })); /// }); @@ -156,7 +156,7 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// // It's even more important here because we `.join` the threads after that. /// // If we had not dropped the lock, a thread could be waiting forever for /// // it, causing a deadlock. -/// std::mem::drop(data); +/// drop(data); /// // Here the lock is not assigned to a variable and so, even if the scope /// // does not end after this line, the mutex is still released: /// // there is no deadlock. From 496818ccd79e9bc093552887c923168defb13c6c Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Mon, 8 Jun 2020 18:31:45 +0200 Subject: [PATCH 05/45] Add methods to go from a nul-terminated Vec to a CString, checked and unchecked. Doc tests have been written and the documentation on the error type updated too. --- src/libstd/ffi/c_str.rs | 80 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 3 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 4bac9a4917d8f..f3a935ccc1130 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -234,15 +234,18 @@ pub struct NulError(usize, Vec); /// An error indicating that a nul byte was not in the expected position. /// -/// The slice used to create a [`CStr`] must have one and only one nul -/// byte at the end of the slice. +/// The slice used to create a [`CStr`] or the vector used to create a +/// [`CString`] must have one and only one nul byte, positioned at the end. /// /// This error is created by the /// [`from_bytes_with_nul`][`CStr::from_bytes_with_nul`] method on -/// [`CStr`]. See its documentation for more. +/// [`CStr`] or the [`from_vec_with_nul`][`CString::from_vec_with_nul`] method +/// on [`CString`]. See their documentation for more. /// /// [`CStr`]: struct.CStr.html /// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul +/// [`CString`]: struct.CString.html +/// [`CString::from_vec_with_nul`]: struct.CString.html#method.from_vec_with_nul /// /// # Examples /// @@ -632,6 +635,77 @@ impl CString { let this = mem::ManuallyDrop::new(self); unsafe { ptr::read(&this.inner) } } + + /// Converts a `Vec` of `u8` to a `CString` without checking the invariants + /// on the given `Vec`. + /// + /// # Safety + /// + /// The given `Vec` **must** have one nul byte as its last element. + /// This means it cannot be empty nor have any other nul byte anywhere else. + /// + /// # Example + /// + /// ``` + /// use std::ffi::CString; + /// assert_eq!( + /// unsafe { CString::from_vec_with_nul_unchecked(b"abc\0".to_vec()) }, + /// unsafe { CString::from_vec_unchecked(b"abc".to_vec()) } + /// ); + /// ``` + #[stable(feature = "cstring_from_vec_with_nul", since = "1.46.0")] + pub unsafe fn from_vec_with_nul_unchecked(v: Vec) -> Self { + Self { inner: v.into_boxed_slice() } + } + + /// Attempts to converts a `Vec` of `u8` to a `CString`. + /// + /// Runtime checks are present to ensure there is only one nul byte in the + /// `Vec`, its last element. + /// + /// # Errors + /// + /// If a nul byte is present and not the last element or no nul bytes + /// is present, an error will be returned. + /// + /// # Examples + /// + /// A successful conversion will produce the same result as [`new`] when + /// called without the ending nul byte. + /// + /// ``` + /// use std::ffi::CString; + /// assert_eq!( + /// CString::from_vec_with_nul(b"abc\0".to_vec()) + /// .expect("CString::from_vec_with_nul failed"), + /// CString::new(b"abc".to_vec()) + /// ); + /// ``` + /// + /// A incorrectly formatted vector will produce an error. + /// + /// ``` + /// use std::ffi::{CString, FromBytesWithNulError}; + /// // Interior nul byte + /// let _: FromBytesWithNulError = CString::from_vec_with_nul(b"a\0bc".to_vec()).unwrap_err(); + /// // No nul byte + /// let _: FromBytesWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err(); + /// ``` + /// + /// [`new`]: #method.new + #[stable(feature = "cstring_from_vec_with_nul", since = "1.46.0")] + pub fn from_vec_with_nul(v: Vec) -> Result { + let nul_pos = memchr::memchr(0, &v); + match nul_pos { + Some(nul_pos) if nul_pos + 1 == v.len() => { + // SAFETY: We know there is only one nul byte, at the end + // of the vec. + Ok(unsafe { Self::from_vec_with_nul_unchecked(v) }) + } + Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)), + None => Err(FromBytesWithNulError::not_nul_terminated()), + } + } } // Turns this `CString` into an empty string to prevent From b03164e6679284b984437fe82092682cf7c984f8 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Tue, 9 Jun 2020 22:15:05 +0200 Subject: [PATCH 06/45] Move to unstable, linking the issue --- src/libstd/ffi/c_str.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index f3a935ccc1130..6f7dc091897f4 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -653,7 +653,7 @@ impl CString { /// unsafe { CString::from_vec_unchecked(b"abc".to_vec()) } /// ); /// ``` - #[stable(feature = "cstring_from_vec_with_nul", since = "1.46.0")] + #[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] pub unsafe fn from_vec_with_nul_unchecked(v: Vec) -> Self { Self { inner: v.into_boxed_slice() } } @@ -693,7 +693,7 @@ impl CString { /// ``` /// /// [`new`]: #method.new - #[stable(feature = "cstring_from_vec_with_nul", since = "1.46.0")] + #[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] pub fn from_vec_with_nul(v: Vec) -> Result { let nul_pos = memchr::memchr(0, &v); match nul_pos { From 1312d30a6a837f72c3f36f5dc1c575a29890aa2c Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Tue, 9 Jun 2020 22:40:30 +0200 Subject: [PATCH 07/45] Remove a lot of unecessary/duplicated comments --- src/libstd/sync/mutex.rs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index c2c86fae654cf..b3ef521d6ecb0 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -118,15 +118,11 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// /// const N: usize = 3; /// -/// // Some data to work with in multiple threads. /// let data_mutex = Arc::new(Mutex::new(vec![1, 2, 3, 4])); -/// // The result of all the work across all threads. /// let res_mutex = Arc::new(Mutex::new(0)); /// -/// // Threads other than the main thread. /// let mut threads = Vec::with_capacity(N); /// (0..N).for_each(|_| { -/// // Getting clones for the mutexes. /// let data_mutex_clone = Arc::clone(&data_mutex); /// let res_mutex_clone = Arc::clone(&res_mutex); /// @@ -135,10 +131,6 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// // This is the result of some important and long-ish work. /// let result = data.iter().fold(0, |acc, x| acc + x * 2); /// data.push(result); -/// // We drop the `data` explicitely because it's not necessary anymore -/// // and the thread still has work to do. This allow other threads to -/// // start working on the data immediately, without waiting -/// // for the rest of the unrelated work to be done here. /// drop(data); /// *res_mutex_clone.lock().unwrap() += result; /// })); @@ -153,9 +145,9 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// // start working on the data immediately, without waiting /// // for the rest of the unrelated work to be done here. /// // -/// // It's even more important here because we `.join` the threads after that. -/// // If we had not dropped the lock, a thread could be waiting forever for -/// // it, causing a deadlock. +/// // It's even more important here than in the threads because we `.join` the +/// // threads after that. If we had not dropped the lock, a thread could be +/// // waiting forever for it, causing a deadlock. /// drop(data); /// // Here the lock is not assigned to a variable and so, even if the scope /// // does not end after this line, the mutex is still released: From 687767af728ce111a7aa24f74cd9068aedb2ab18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 29 May 2020 15:09:43 -0700 Subject: [PATCH 08/45] Suggest substituting `'static` lifetime in impl/dyn `Trait + 'static` return types --- .../nice_region_error/static_impl_trait.rs | 64 ++++++++-- src/librustc_middle/ty/context.rs | 13 +- src/librustc_middle/ty/diagnostics.rs | 8 +- ...t_outlive_least_region_or_bound.nll.stderr | 38 +++++- .../must_outlive_least_region_or_bound.rs | 21 ++++ .../must_outlive_least_region_or_bound.stderr | 117 ++++++++++++++++-- 6 files changed, 232 insertions(+), 29 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index f4c86ddae604e..88d6c23d51441 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -4,6 +4,7 @@ use crate::infer::error_reporting::msg_span_from_free_region; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use rustc_errors::{Applicability, ErrorReported}; +use rustc_hir::{GenericBound, ItemKind, Lifetime, LifetimeName, TyKind}; use rustc_middle::ty::RegionKind; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { @@ -20,8 +21,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ) = error.clone() { let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?; - let (fn_return_span, is_dyn) = - self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?; + let fn_return = self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?; + let is_dyn = matches!(fn_return.kind, TyKind::TraitObject(..)); + let fn_return_span = fn_return.span; if sub_r == &RegionKind::ReStatic { let sp = var_origin.span(); let return_sp = sub_origin.span(); @@ -67,12 +69,58 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { lifetime, ); // FIXME: account for the need of parens in `&(dyn Trait + '_)` - err.span_suggestion_verbose( - fn_return_span.shrink_to_hi(), - &msg, - format!(" + {}", lifetime_name), - Applicability::MaybeIncorrect, - ); + match fn_return.kind { + TyKind::Def(item_id, _) => { + let item = self.tcx().hir().item(item_id.id); + let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind { + opaque + } else { + err.emit(); + return Some(ErrorReported); + }; + let (span, sugg) = opaque + .bounds + .iter() + .filter_map(|arg| match arg { + GenericBound::Outlives(Lifetime { + name: LifetimeName::Static, + span, + .. + }) => Some((*span, lifetime_name.clone())), + _ => None, + }) + .next() + .unwrap_or_else(|| { + ( + fn_return_span.shrink_to_hi(), + format!(" + {}", lifetime_name), + ) + }); + + err.span_suggestion_verbose( + span, + &msg, + sugg, + Applicability::MaybeIncorrect, + ); + } + TyKind::TraitObject(_, lt) => { + let (span, sugg) = match lt.name { + LifetimeName::ImplicitObjectLifetimeDefault => ( + fn_return_span.shrink_to_hi(), + format!(" + {}", lifetime_name), + ), + _ => (lt.span, lifetime_name), + }; + err.span_suggestion_verbose( + span, + &msg, + sugg, + Applicability::MaybeIncorrect, + ); + } + _ => {} + } } err.emit(); return Some(ErrorReported); diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index d5be3508d2d80..4770993d9cb07 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -1383,7 +1383,10 @@ impl<'tcx> TyCtxt<'tcx> { }) } - pub fn return_type_impl_or_dyn_trait(&self, scope_def_id: DefId) -> Option<(Span, bool)> { + pub fn return_type_impl_or_dyn_trait( + &self, + scope_def_id: DefId, + ) -> Option<&'tcx hir::Ty<'tcx>> { let hir_id = self.hir().as_local_hir_id(scope_def_id.expect_local()); let hir_output = match self.hir().get(hir_id) { Node::Item(hir::Item { @@ -1429,15 +1432,17 @@ impl<'tcx> TyCtxt<'tcx> { let output = self.erase_late_bound_regions(&sig.output()); if output.is_impl_trait() { let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap(); - Some((fn_decl.output.span(), false)) + if let hir::FnRetTy::Return(ty) = fn_decl.output { + return Some(ty); + } } else { let mut v = TraitObjectVisitor(vec![]); rustc_hir::intravisit::walk_ty(&mut v, hir_output); if v.0.len() == 1 { - return Some((v.0[0], true)); + return Some(v.0[0]); } - None } + None } _ => None, } diff --git a/src/librustc_middle/ty/diagnostics.rs b/src/librustc_middle/ty/diagnostics.rs index 2e9aa724ac5af..3ca506fe0d590 100644 --- a/src/librustc_middle/ty/diagnostics.rs +++ b/src/librustc_middle/ty/diagnostics.rs @@ -236,21 +236,21 @@ pub fn suggest_constraining_type_param( } } -pub struct TraitObjectVisitor(pub Vec); -impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor { +pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>); +impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { type Map = rustc_hir::intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { hir::intravisit::NestedVisitorMap::None } - fn visit_ty(&mut self, ty: &hir::Ty<'_>) { + fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { if let hir::TyKind::TraitObject( _, hir::Lifetime { name: hir::LifetimeName::ImplicitObjectLifetimeDefault, .. }, ) = ty.kind { - self.0.push(ty.span); + self.0.push(ty); } } } diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr index 1806d2607a3ac..ca9ca8a9debe2 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr @@ -26,7 +26,34 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^^^^^^^^^^^ error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:12:69 + --> $DIR/must_outlive_least_region_or_bound.rs:9:46 + | +LL | fn elided2(x: &i32) -> impl Copy + 'static { x } + | - ^ returning this value requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + | + = help: consider replacing `'1` with `'static` + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:12:55 + | +LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } + | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` + | + = help: consider replacing `'a` with `'static` + = help: consider replacing `'a` with `'static` + +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/must_outlive_least_region_or_bound.rs:15:41 + | +LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } + | ---- ^ lifetime `'a` required + | | + | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:33:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` @@ -35,7 +62,7 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } = help: consider replacing `'a` with `'static` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:17:61 + --> $DIR/must_outlive_least_region_or_bound.rs:38:61 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { | -- -- lifetime `'b` defined here ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a` @@ -45,13 +72,14 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 = help: consider adding the following bound: `'b: 'a` error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:22:51 + --> $DIR/must_outlive_least_region_or_bound.rs:43:51 | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | ^^^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `T: 'static`... -error: aborting due to 5 previous errors +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0310`. +Some errors have detailed explanations: E0310, E0621. +For more information about an error, try `rustc --explain E0310`. diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs index 00f3490991b52..beafe9258209d 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -6,6 +6,27 @@ fn elided(x: &i32) -> impl Copy { x } fn explicit<'a>(x: &'a i32) -> impl Copy { x } //~^ ERROR cannot infer an appropriate lifetime +fn elided2(x: &i32) -> impl Copy + 'static { x } +//~^ ERROR cannot infer an appropriate lifetime + +fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } +//~^ ERROR cannot infer an appropriate lifetime + +fn foo<'a>(x: &i32) -> impl Copy + 'a { x } +//~^ ERROR explicit lifetime required in the type of `x` + +fn elided3(x: &i32) -> Box { Box::new(x) } +//~^ ERROR cannot infer an appropriate lifetime + +fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } +//~^ ERROR cannot infer an appropriate lifetime + +fn elided4(x: &i32) -> Box { Box::new(x) } +//~^ ERROR explicit lifetime required in the type of `x` + +fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } +//~^ ERROR cannot infer an appropriate lifetime + trait LifetimeTrait<'a> {} impl<'a> LifetimeTrait<'a> for &'a i32 {} diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index d7dae6a08a7b9..525e271bea9c3 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -27,7 +27,43 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^ error: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:12:69 + --> $DIR/must_outlive_least_region_or_bound.rs:9:46 + | +LL | fn elided2(x: &i32) -> impl Copy + 'static { x } + | ---- ------------------- ^ ...and is captured here + | | | + | | ...is required to be `'static` by this... + | data with this lifetime... + | +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 9:1 + | +LL | fn elided2(x: &i32) -> impl Copy + '_ { x } + | ^^ + +error: cannot infer an appropriate lifetime + --> $DIR/must_outlive_least_region_or_bound.rs:12:55 + | +LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } + | ------- ------------------- ^ ...and is captured here + | | | + | | ...is required to be `'static` by this... + | data with this lifetime... + | +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 12:14 + | +LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } + | ^^ + +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/must_outlive_least_region_or_bound.rs:15:24 + | +LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } + | ---- ^^^^^^^^^^^^^^ lifetime `'a` required + | | + | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` + +error: cannot infer an appropriate lifetime + --> $DIR/must_outlive_least_region_or_bound.rs:33:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ------- -------------------------------- ^ ...and is captured here @@ -35,13 +71,13 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | | ...is required to be `'static` by this... | data with this lifetime... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 12:15 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 33:15 | -LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x } - | ^^^^ +LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x } + | ^^ error[E0623]: lifetime mismatch - --> $DIR/must_outlive_least_region_or_bound.rs:17:61 + --> $DIR/must_outlive_least_region_or_bound.rs:38:61 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { | ------- ^^^^^^^^^^^^^^^^ @@ -50,14 +86,79 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 | this parameter and the return type are declared with different lifetimes... error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:22:51 + --> $DIR/must_outlive_least_region_or_bound.rs:43:51 | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | | | help: consider adding an explicit lifetime bound...: `T: 'static +` -error: aborting due to 5 previous errors +error: cannot infer an appropriate lifetime + --> $DIR/must_outlive_least_region_or_bound.rs:18:50 + | +LL | fn elided3(x: &i32) -> Box { Box::new(x) } + | ---- ---------^- + | | | | + | | | ...and is captured here + | | ...is required to be `'static` by this... + | data with this lifetime... + | +help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 18:1 + | +LL | fn elided3(x: &i32) -> Box { Box::new(x) } + | ^^^^ + +error: cannot infer an appropriate lifetime + --> $DIR/must_outlive_least_region_or_bound.rs:21:59 + | +LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } + | ------- ---------^- + | | | | + | | | ...and is captured here + | | ...is required to be `'static` by this... + | data with this lifetime... + | +help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 21:14 + | +LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^^^^ + +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/must_outlive_least_region_or_bound.rs:24:51 + | +LL | fn elided4(x: &i32) -> Box { Box::new(x) } + | ---- ^^^^^^^^^^^ lifetime `'static` required + | | + | help: add explicit lifetime `'static` to the type of `x`: `&'static i32` + +error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements + --> $DIR/must_outlive_least_region_or_bound.rs:27:69 + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^ + | +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 27:14... + --> $DIR/must_outlive_least_region_or_bound.rs:27:14 + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^^ +note: ...so that the expression is assignable + --> $DIR/must_outlive_least_region_or_bound.rs:27:69 + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^ + = note: expected `&i32` + found `&'a i32` + = note: but, the lifetime must be valid for the static lifetime... +note: ...so that the expression is assignable + --> $DIR/must_outlive_least_region_or_bound.rs:27:60 + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^ + = note: expected `std::boxed::Box<(dyn std::fmt::Debug + 'static)>` + found `std::boxed::Box` + +error: aborting due to 12 previous errors -Some errors have detailed explanations: E0310, E0623. +Some errors have detailed explanations: E0310, E0495, E0621, E0623. For more information about an error, try `rustc --explain E0310`. From c91320f06b0b967b662f62a1c00447b9c87d4542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 29 May 2020 18:05:20 -0700 Subject: [PATCH 09/45] When `'static` is explicit, suggest constraining argument with it --- .../infer/error_reporting/mod.rs | 3 +- .../nice_region_error/static_impl_trait.rs | 115 +++++++++++------- src/librustc_middle/ty/diagnostics.rs | 5 +- .../must_outlive_least_region_or_bound.rs | 2 +- .../must_outlive_least_region_or_bound.stderr | 75 +++++++----- src/test/ui/issues/issue-16922.stderr | 2 +- ...ect-lifetime-default-from-box-error.stderr | 2 +- ...ion-object-lifetime-in-coercion.nll.stderr | 19 ++- .../region-object-lifetime-in-coercion.rs | 5 +- .../region-object-lifetime-in-coercion.stderr | 61 +++++++--- .../regions-close-object-into-object-2.stderr | 32 ++--- .../regions-close-object-into-object-4.stderr | 32 ++--- .../regions-proc-bound-capture.nll.stderr | 11 ++ .../ui/regions/regions-proc-bound-capture.rs | 4 +- .../regions/regions-proc-bound-capture.stderr | 25 ++-- .../dyn-trait-underscore.stderr | 2 +- 16 files changed, 237 insertions(+), 158 deletions(-) create mode 100644 src/test/ui/regions/regions-proc-bound-capture.nll.stderr diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index a59a91e3005aa..f7969fe779d33 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -2037,8 +2037,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.sess, var_origin.span(), E0495, - "cannot infer an appropriate lifetime{} \ - due to conflicting requirements", + "cannot infer an appropriate lifetime{} due to conflicting requirements", var_description ) } diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 88d6c23d51441..e24535bba5fdc 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -10,6 +10,7 @@ use rustc_middle::ty::RegionKind; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the return type is a static impl Trait. pub(super) fn try_report_static_impl_trait(&self) -> Option { + debug!("try_report_static_impl_trait(error={:?})", self.error); if let Some(ref error) = self.error { if let RegionResolutionError::SubSupConflict( _, @@ -18,19 +19,24 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { sub_r, sup_origin, sup_r, - ) = error.clone() + ) = error { + debug!( + "try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})", + var_origin, sub_origin, sub_r, sup_origin, sup_r + ); let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?; + debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup); let fn_return = self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?; - let is_dyn = matches!(fn_return.kind, TyKind::TraitObject(..)); - let fn_return_span = fn_return.span; - if sub_r == &RegionKind::ReStatic { + debug!("try_report_static_impl_trait: fn_return={:?}", fn_return); + if **sub_r == RegionKind::ReStatic { let sp = var_origin.span(); let return_sp = sub_origin.span(); + let param_info = self.find_param_with_region(sup_r, sub_r)?; let mut err = self.tcx().sess.struct_span_err(sp, "cannot infer an appropriate lifetime"); - let param_info = self.find_param_with_region(sup_r, sub_r)?; err.span_label(param_info.param_ty_span, "data with this lifetime..."); + debug!("try_report_static_impl_trait: param_info={:?}", param_info); // We try to make the output have fewer overlapping spans if possible. if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span())) @@ -60,14 +66,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() }; // only apply this suggestion onto functions with // explicit non-desugar'able return. - if fn_return_span.desugaring_kind().is_none() { - let msg = format!( - "to permit non-static references in {} `{} Trait` value, you can add \ - an explicit bound for {}", - if is_dyn { "a" } else { "an" }, - if is_dyn { "dyn" } else { "impl" }, - lifetime, - ); + if fn_return.span.desugaring_kind().is_none() { // FIXME: account for the need of parens in `&(dyn Trait + '_)` match fn_return.kind { TyKind::Def(item_id, _) => { @@ -78,7 +77,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { err.emit(); return Some(ErrorReported); }; - let (span, sugg) = opaque + + if let Some(span) = opaque .bounds .iter() .filter_map(|arg| match arg { @@ -86,38 +86,71 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { name: LifetimeName::Static, span, .. - }) => Some((*span, lifetime_name.clone())), + }) => Some(*span), _ => None, }) .next() - .unwrap_or_else(|| { - ( - fn_return_span.shrink_to_hi(), - format!(" + {}", lifetime_name), - ) - }); - - err.span_suggestion_verbose( - span, - &msg, - sugg, - Applicability::MaybeIncorrect, - ); - } - TyKind::TraitObject(_, lt) => { - let (span, sugg) = match lt.name { - LifetimeName::ImplicitObjectLifetimeDefault => ( - fn_return_span.shrink_to_hi(), + { + err.span_suggestion_verbose( + span, + "consider changing the `impl Trait`'s explicit \ + `'static` bound", + lifetime_name, + Applicability::MaybeIncorrect, + ); + err.span_suggestion_verbose( + param_info.param_ty_span, + "alternatively, set an explicit `'static` lifetime to \ + this parameter", + param_info.param_ty.to_string(), + Applicability::MaybeIncorrect, + ); + } else { + err.span_suggestion_verbose( + fn_return.span.shrink_to_hi(), + &format!( + "to permit non-static references in an `impl Trait` \ + value, you can add an explicit bound for {}", + lifetime, + ), format!(" + {}", lifetime_name), - ), - _ => (lt.span, lifetime_name), + Applicability::MaybeIncorrect, + ); }; - err.span_suggestion_verbose( - span, - &msg, - sugg, - Applicability::MaybeIncorrect, - ); + } + TyKind::TraitObject(_, lt) => { + match lt.name { + LifetimeName::ImplicitObjectLifetimeDefault => { + err.span_suggestion_verbose( + fn_return.span.shrink_to_hi(), + &format!( + "to permit non-static references in a trait object \ + value, you can add an explicit bound for {}", + lifetime, + ), + format!(" + {}", lifetime_name), + Applicability::MaybeIncorrect, + ); + } + _ => { + err.span_suggestion_verbose( + lt.span, + "consider changing the trait object's explicit \ + `'static` bound", + lifetime_name, + Applicability::MaybeIncorrect, + ); + err.span_suggestion_verbose( + param_info.param_ty_span, + &format!( + "alternatively, set an explicit `'static` lifetime \ + in this parameter", + ), + param_info.param_ty.to_string(), + Applicability::MaybeIncorrect, + ); + } + } } _ => {} } diff --git a/src/librustc_middle/ty/diagnostics.rs b/src/librustc_middle/ty/diagnostics.rs index 3ca506fe0d590..a2812e117ed39 100644 --- a/src/librustc_middle/ty/diagnostics.rs +++ b/src/librustc_middle/ty/diagnostics.rs @@ -247,7 +247,10 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { if let hir::TyKind::TraitObject( _, - hir::Lifetime { name: hir::LifetimeName::ImplicitObjectLifetimeDefault, .. }, + hir::Lifetime { + name: hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static, + .. + }, ) = ty.kind { self.0.push(ty); diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs index beafe9258209d..837244b022721 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -22,7 +22,7 @@ fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } //~^ ERROR cannot infer an appropriate lifetime fn elided4(x: &i32) -> Box { Box::new(x) } -//~^ ERROR explicit lifetime required in the type of `x` +//~^ ERROR cannot infer an appropriate lifetime fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } //~^ ERROR cannot infer an appropriate lifetime diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 525e271bea9c3..96d4a121c16af 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -35,10 +35,14 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | | ...is required to be `'static` by this... | data with this lifetime... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 9:1 +help: consider changing the `impl Trait`'s explicit `'static` bound | LL | fn elided2(x: &i32) -> impl Copy + '_ { x } | ^^ +help: alternatively, set an explicit `'static` lifetime to this parameter + | +LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x } + | ^^^^^^^^^^^^ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:12:55 @@ -49,10 +53,14 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | | ...is required to be `'static` by this... | data with this lifetime... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 12:14 +help: consider changing the `impl Trait`'s explicit `'static` bound | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^ +help: alternatively, set an explicit `'static` lifetime to this parameter + | +LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x } + | ^^^^^^^^^^^^ error[E0621]: explicit lifetime required in the type of `x` --> $DIR/must_outlive_least_region_or_bound.rs:15:24 @@ -71,10 +79,14 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | | ...is required to be `'static` by this... | data with this lifetime... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 33:15 +help: consider changing the `impl Trait`'s explicit `'static` bound | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x } | ^^ +help: alternatively, set an explicit `'static` lifetime to this parameter + | +LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x } + | ^^^^^^^^^^^^ error[E0623]: lifetime mismatch --> $DIR/must_outlive_least_region_or_bound.rs:38:61 @@ -103,7 +115,7 @@ LL | fn elided3(x: &i32) -> Box { Box::new(x) } | | ...is required to be `'static` by this... | data with this lifetime... | -help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 18:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 18:1 | LL | fn elided3(x: &i32) -> Box { Box::new(x) } | ^^^^ @@ -118,47 +130,48 @@ LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | | ...is required to be `'static` by this... | data with this lifetime... | -help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 21:14 +help: to permit non-static references in a trait object value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 21:14 | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^^^ -error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/must_outlive_least_region_or_bound.rs:24:51 +error: cannot infer an appropriate lifetime + --> $DIR/must_outlive_least_region_or_bound.rs:24:60 | LL | fn elided4(x: &i32) -> Box { Box::new(x) } - | ---- ^^^^^^^^^^^ lifetime `'static` required - | | - | help: add explicit lifetime `'static` to the type of `x`: `&'static i32` - -error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements - --> $DIR/must_outlive_least_region_or_bound.rs:27:69 + | ---- ---------^- + | | | | + | | | ...and is captured here + | data with this lifetime... ...is required to be `'static` by this... | -LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ^ +help: consider changing the trait object's explicit `'static` bound | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 27:14... - --> $DIR/must_outlive_least_region_or_bound.rs:27:14 +LL | fn elided4(x: &i32) -> Box { Box::new(x) } + | ^^ +help: alternatively, set an explicit `'static` lifetime in this parameter | -LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ^^ -note: ...so that the expression is assignable +LL | fn elided4(x: &'static i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^^ + +error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:27:69 | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ^ - = note: expected `&i32` - found `&'a i32` - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the expression is assignable - --> $DIR/must_outlive_least_region_or_bound.rs:27:60 + | ------- ---------^- + | | | | + | | | ...and is captured here + | data with this lifetime... ...is required to be `'static` by this... | -LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ^^^^^^^^^^^ - = note: expected `std::boxed::Box<(dyn std::fmt::Debug + 'static)>` - found `std::boxed::Box` +help: consider changing the trait object's explicit `'static` bound + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^^ +help: alternatively, set an explicit `'static` lifetime in this parameter + | +LL | fn explicit4<'a>(x: &'static i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^^ error: aborting due to 12 previous errors -Some errors have detailed explanations: E0310, E0495, E0621, E0623. +Some errors have detailed explanations: E0310, E0621, E0623. For more information about an error, try `rustc --explain E0310`. diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 02d33aae023ff..038df47e1bd98 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -9,7 +9,7 @@ LL | Box::new(value) as Box | | ...and is captured here | ...is required to be `'static` by this... | -help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1 | LL | fn foo(value: &T) -> Box { | ^^^^ diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index 70a9bf22b8db3..555622c9d13c1 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -7,7 +7,7 @@ LL | fn load(ss: &mut SomeStruct) -> Box { LL | ss.r | ^^^^ ...is captured and required to be `'static` here | -help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #2 defined on the function body at 14:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #2 defined on the function body at 14:1 | LL | fn load(ss: &mut SomeStruct) -> Box { | ^^^^ diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr index bf02ba8eb9199..7e8f78067e08a 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr @@ -1,21 +1,21 @@ -error[E0621]: explicit lifetime required in the type of `v` +error: lifetime may not live long enough --> $DIR/region-object-lifetime-in-coercion.rs:8:12 | LL | fn a(v: &[u8]) -> Box { - | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]` + | - let's call the lifetime of this reference `'1` LL | let x: Box = Box::new(v); - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required + | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static` -error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/region-object-lifetime-in-coercion.rs:14:5 +error: lifetime may not live long enough + --> $DIR/region-object-lifetime-in-coercion.rs:13:5 | LL | fn b(v: &[u8]) -> Box { - | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]` + | - let's call the lifetime of this reference `'1` LL | Box::new(v) - | ^^^^^^^^^^^ lifetime `'static` required + | ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` error: lifetime may not live long enough - --> $DIR/region-object-lifetime-in-coercion.rs:20:5 + --> $DIR/region-object-lifetime-in-coercion.rs:19:5 | LL | fn c(v: &[u8]) -> Box { | - let's call the lifetime of this reference `'1` @@ -24,7 +24,7 @@ LL | Box::new(v) | ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` error: lifetime may not live long enough - --> $DIR/region-object-lifetime-in-coercion.rs:24:5 + --> $DIR/region-object-lifetime-in-coercion.rs:23:5 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { | -- -- lifetime `'b` defined here @@ -37,4 +37,3 @@ LL | Box::new(v) error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.rs b/src/test/ui/regions/region-object-lifetime-in-coercion.rs index d56eaf77b6646..5d199149c39b8 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.rs +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.rs @@ -5,13 +5,12 @@ trait Foo {} impl<'a> Foo for &'a [u8] {} fn a(v: &[u8]) -> Box { - let x: Box = Box::new(v); - //~^ ERROR explicit lifetime required in the type of `v` [E0621] + let x: Box = Box::new(v); //~ ERROR cannot infer an appropriate lifetime x } fn b(v: &[u8]) -> Box { - Box::new(v) //~ ERROR explicit lifetime required in the type of `v` [E0621] + Box::new(v) //~ ERROR cannot infer an appropriate lifetime } fn c(v: &[u8]) -> Box { diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 1462af44cb15a..673300cebc26c 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -1,21 +1,45 @@ -error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/region-object-lifetime-in-coercion.rs:8:37 +error: cannot infer an appropriate lifetime + --> $DIR/region-object-lifetime-in-coercion.rs:8:46 | LL | fn a(v: &[u8]) -> Box { - | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]` + | ----- data with this lifetime... LL | let x: Box = Box::new(v); - | ^^^^^^^^^^^ lifetime `'static` required + | ---------^- + | | | + | | ...and is captured here + | ...is required to be `'static` by this... + | +help: consider changing the trait object's explicit `'static` bound + | +LL | fn a(v: &[u8]) -> Box { + | ^^ +help: alternatively, set an explicit `'static` lifetime in this parameter + | +LL | fn a(v: &'static [u8]) -> Box { + | ^^^^^^^^^^^^^ -error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/region-object-lifetime-in-coercion.rs:14:5 +error: cannot infer an appropriate lifetime + --> $DIR/region-object-lifetime-in-coercion.rs:13:14 | LL | fn b(v: &[u8]) -> Box { - | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]` + | ----- data with this lifetime... LL | Box::new(v) - | ^^^^^^^^^^^ lifetime `'static` required + | ---------^- + | | | + | | ...and is captured here + | ...is required to be `'static` by this... + | +help: consider changing the trait object's explicit `'static` bound + | +LL | fn b(v: &[u8]) -> Box { + | ^^ +help: alternatively, set an explicit `'static` lifetime in this parameter + | +LL | fn b(v: &'static [u8]) -> Box { + | ^^^^^^^^^^^^^ error: cannot infer an appropriate lifetime - --> $DIR/region-object-lifetime-in-coercion.rs:20:14 + --> $DIR/region-object-lifetime-in-coercion.rs:19:14 | LL | fn c(v: &[u8]) -> Box { | ----- data with this lifetime... @@ -26,36 +50,36 @@ LL | Box::new(v) | | ...and is captured here | ...is required to be `'static` by this... | -help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 17:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 16:1 | LL | fn c(v: &[u8]) -> Box { | ^^^^ error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements - --> $DIR/region-object-lifetime-in-coercion.rs:24:14 + --> $DIR/region-object-lifetime-in-coercion.rs:23:14 | LL | Box::new(v) | ^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 23:6... - --> $DIR/region-object-lifetime-in-coercion.rs:23:6 +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:6... + --> $DIR/region-object-lifetime-in-coercion.rs:22:6 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { | ^^ note: ...so that the expression is assignable - --> $DIR/region-object-lifetime-in-coercion.rs:24:14 + --> $DIR/region-object-lifetime-in-coercion.rs:23:14 | LL | Box::new(v) | ^ = note: expected `&[u8]` found `&'a [u8]` -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 23:9... - --> $DIR/region-object-lifetime-in-coercion.rs:23:9 +note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 22:9... + --> $DIR/region-object-lifetime-in-coercion.rs:22:9 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { | ^^ note: ...so that the expression is assignable - --> $DIR/region-object-lifetime-in-coercion.rs:24:5 + --> $DIR/region-object-lifetime-in-coercion.rs:23:5 | LL | Box::new(v) | ^^^^^^^^^^^ @@ -64,5 +88,4 @@ LL | Box::new(v) error: aborting due to 4 previous errors -Some errors have detailed explanations: E0495, E0621. -For more information about an error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 147f7f3541816..982ed07232a80 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -1,28 +1,22 @@ -error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements +error: cannot infer an appropriate lifetime --> $DIR/regions-close-object-into-object-2.rs:10:11 | +LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { + | ------------------ data with this lifetime... LL | box B(&*v) as Box - | ^^^ - | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:6... - --> $DIR/regions-close-object-into-object-2.rs:9:6 + | ------^^^--------------- + | | | + | | ...and is captured here + | ...is required to be `'static` by this... | -LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { - | ^^ -note: ...so that the type `(dyn A + 'a)` is not borrowed for too long - --> $DIR/regions-close-object-into-object-2.rs:10:11 +help: consider changing the trait object's explicit `'static` bound | -LL | box B(&*v) as Box - | ^^^ - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the expression is assignable - --> $DIR/regions-close-object-into-object-2.rs:10:5 +LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { + | ^^ +help: alternatively, set an explicit `'static` lifetime in this parameter | -LL | box B(&*v) as Box - | ^^^^^^^^^^^^^^^^^^^^^^^^ - = note: expected `std::boxed::Box<(dyn X + 'static)>` - found `std::boxed::Box` +LL | fn g<'a, T: 'static>(v: std::boxed::Box<(dyn A + 'static)>) -> Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index 6e7d6152cd09a..1b82098ee13c2 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -1,28 +1,22 @@ -error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements +error: cannot infer an appropriate lifetime --> $DIR/regions-close-object-into-object-4.rs:10:11 | +LL | fn i<'a, T, U>(v: Box+'a>) -> Box { + | ---------------- data with this lifetime... LL | box B(&*v) as Box - | ^^^ - | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:6... - --> $DIR/regions-close-object-into-object-4.rs:9:6 + | ------^^^--------------- + | | | + | | ...and is captured here + | ...is required to be `'static` by this... | -LL | fn i<'a, T, U>(v: Box+'a>) -> Box { - | ^^ -note: ...so that the type `(dyn A + 'a)` is not borrowed for too long - --> $DIR/regions-close-object-into-object-4.rs:10:11 +help: consider changing the trait object's explicit `'static` bound | -LL | box B(&*v) as Box - | ^^^ - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the expression is assignable - --> $DIR/regions-close-object-into-object-4.rs:10:5 +LL | fn i<'a, T, U>(v: Box+'a>) -> Box { + | ^^ +help: alternatively, set an explicit `'static` lifetime in this parameter | -LL | box B(&*v) as Box - | ^^^^^^^^^^^^^^^^^^^^^^^^ - = note: expected `std::boxed::Box<(dyn X + 'static)>` - found `std::boxed::Box` +LL | fn i<'a, T, U>(v: std::boxed::Box<(dyn A + 'static)>) -> Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-proc-bound-capture.nll.stderr b/src/test/ui/regions/regions-proc-bound-capture.nll.stderr new file mode 100644 index 0000000000000..75890b8581537 --- /dev/null +++ b/src/test/ui/regions/regions-proc-bound-capture.nll.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/regions-proc-bound-capture.rs:9:5 + | +LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { + | - let's call the lifetime of this reference `'1` +LL | // This is illegal, because the region bound on `proc` is 'static. +LL | Box::new(move || { *x }) + | ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to previous error + diff --git a/src/test/ui/regions/regions-proc-bound-capture.rs b/src/test/ui/regions/regions-proc-bound-capture.rs index 0c903b7384992..8617c0e9da8f7 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.rs +++ b/src/test/ui/regions/regions-proc-bound-capture.rs @@ -4,9 +4,9 @@ fn borrowed_proc<'a>(x: &'a isize) -> Box(isize) + 'a> { Box::new(move|| { *x }) } -fn static_proc(x: &isize) -> Box(isize) + 'static> { +fn static_proc(x: &isize) -> Box (isize) + 'static> { // This is illegal, because the region bound on `proc` is 'static. - Box::new(move|| { *x }) //~ ERROR explicit lifetime required in the type of `x` [E0621] + Box::new(move || { *x }) //~ ERROR cannot infer an appropriate lifetime } fn main() { } diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index c53af34456ef3..e7bbfaababe8a 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -1,12 +1,23 @@ -error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/regions-proc-bound-capture.rs:9:5 +error: cannot infer an appropriate lifetime + --> $DIR/regions-proc-bound-capture.rs:9:14 | -LL | fn static_proc(x: &isize) -> Box(isize) + 'static> { - | ------ help: add explicit lifetime `'static` to the type of `x`: `&'static isize` +LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { + | ------ data with this lifetime... LL | // This is illegal, because the region bound on `proc` is 'static. -LL | Box::new(move|| { *x }) - | ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required +LL | Box::new(move || { *x }) + | ---------^^^^^^^^^^^^^^- + | | | + | | ...and is captured here + | ...is required to be `'static` by this... + | +help: consider changing the trait object's explicit `'static` bound + | +LL | fn static_proc(x: &isize) -> Box (isize) + '_> { + | ^^ +help: alternatively, set an explicit `'static` lifetime in this parameter + | +LL | fn static_proc(x: &'static isize) -> Box (isize) + 'static> { + | ^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index 3577dd59289e5..4dc4aac6ceac4 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -7,7 +7,7 @@ LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to LL | Box::new(items.iter()) | ---------------^^^^--- ...is captured and required to be `'static` here | -help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 6:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 6:1 | LL | fn a(items: &[T]) -> Box + '_> { | ^^^^ From abf74b9e729463a18f5da1d79cecaf9f4fc07d17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 29 May 2020 18:59:42 -0700 Subject: [PATCH 10/45] Reduce verbosity of suggestion message and mention lifetime in label --- .../nice_region_error/static_impl_trait.rs | 87 ++++++++++--------- .../ui/async-await/issues/issue-62097.stderr | 2 +- .../must_outlive_least_region_or_bound.stderr | 38 ++++---- .../static-return-lifetime-infered.stderr | 8 +- src/test/ui/issues/issue-16922.stderr | 4 +- ...ect-lifetime-default-from-box-error.stderr | 4 +- .../region-object-lifetime-in-coercion.stderr | 12 +-- .../regions-close-object-into-object-2.stderr | 4 +- .../regions-close-object-into-object-4.stderr | 4 +- .../regions/regions-proc-bound-capture.stderr | 4 +- ...types_pin_lifetime_impl_trait-async.stderr | 2 +- ..._self_types_pin_lifetime_impl_trait.stderr | 4 +- .../missing-lifetimes-in-signature.stderr | 4 +- .../dyn-trait-underscore.stderr | 4 +- 14 files changed, 95 insertions(+), 86 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index e24535bba5fdc..e9f165d309f8f 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -1,6 +1,5 @@ //! Error Reporting for static impl Traits. -use crate::infer::error_reporting::msg_span_from_free_region; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use rustc_errors::{Applicability, ErrorReported}; @@ -33,9 +32,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let sp = var_origin.span(); let return_sp = sub_origin.span(); let param_info = self.find_param_with_region(sup_r, sub_r)?; + let (lifetime_name, lifetime) = if sup_r.has_name() { + (sup_r.to_string(), format!("lifetime `{}`", sup_r)) + } else { + ("'_".to_owned(), "the anonymous lifetime `'_`".to_string()) + }; let mut err = self.tcx().sess.struct_span_err(sp, "cannot infer an appropriate lifetime"); - err.span_label(param_info.param_ty_span, "data with this lifetime..."); + err.span_label( + param_info.param_ty_span, + &format!("this data with {}...", lifetime), + ); debug!("try_report_static_impl_trait: param_info={:?}", param_info); // We try to make the output have fewer overlapping spans if possible. @@ -60,10 +67,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ); } - let (lifetime, _) = msg_span_from_free_region(self.tcx(), sup_r); - - let lifetime_name = - if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() }; // only apply this suggestion onto functions with // explicit non-desugar'able return. if fn_return.span.desugaring_kind().is_none() { @@ -93,8 +96,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { { err.span_suggestion_verbose( span, - "consider changing the `impl Trait`'s explicit \ - `'static` bound", + &format!( + "consider changing the `impl Trait`'s explicit \ + `'static` bound to {}", + lifetime, + ), lifetime_name, Applicability::MaybeIncorrect, ); @@ -118,40 +124,41 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ); }; } - TyKind::TraitObject(_, lt) => { - match lt.name { - LifetimeName::ImplicitObjectLifetimeDefault => { - err.span_suggestion_verbose( - fn_return.span.shrink_to_hi(), - &format!( - "to permit non-static references in a trait object \ - value, you can add an explicit bound for {}", - lifetime, - ), - format!(" + {}", lifetime_name), - Applicability::MaybeIncorrect, - ); - } - _ => { - err.span_suggestion_verbose( - lt.span, + TyKind::TraitObject(_, lt) => match lt.name { + LifetimeName::ImplicitObjectLifetimeDefault => { + err.span_suggestion_verbose( + fn_return.span.shrink_to_hi(), + &format!( + "to permit non-static references in a trait object \ + value, you can add an explicit bound for {}", + lifetime, + ), + format!(" + {}", lifetime_name), + Applicability::MaybeIncorrect, + ); + } + _ => { + err.span_suggestion_verbose( + lt.span, + &format!( "consider changing the trait object's explicit \ - `'static` bound", - lifetime_name, - Applicability::MaybeIncorrect, - ); - err.span_suggestion_verbose( - param_info.param_ty_span, - &format!( - "alternatively, set an explicit `'static` lifetime \ - in this parameter", - ), - param_info.param_ty.to_string(), - Applicability::MaybeIncorrect, - ); - } + `'static` bound to {}", + lifetime, + ), + lifetime_name, + Applicability::MaybeIncorrect, + ); + err.span_suggestion_verbose( + param_info.param_ty_span, + &format!( + "alternatively, set an explicit `'static` lifetime \ + in this parameter", + ), + param_info.param_ty.to_string(), + Applicability::MaybeIncorrect, + ); } - } + }, _ => {} } } diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index af8fc2cd2ab45..fff43ae9f47bc 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -4,7 +4,7 @@ error: cannot infer an appropriate lifetime LL | pub async fn run_dummy_fn(&self) { | ^^^^^ | | - | data with this lifetime... + | this data with the anonymous lifetime `'_`... | ...is captured here... LL | foo(|| self.bar()).await; | --- ...and required to be `'static` by this diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 96d4a121c16af..00b6ec38323c3 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -5,9 +5,9 @@ LL | fn elided(x: &i32) -> impl Copy { x } | ---- --------- ^ ...and is captured here | | | | | ...is required to be `'static` by this... - | data with this lifetime... + | this data with the anonymous lifetime `'_`... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ^^^^ @@ -19,9 +19,9 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | ------- --------- ^ ...and is captured here | | | | | ...is required to be `'static` by this... - | data with this lifetime... + | this data with lifetime `'a`... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 6:13 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for lifetime `'a` | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^ @@ -33,9 +33,9 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | ---- ------------------- ^ ...and is captured here | | | | | ...is required to be `'static` by this... - | data with this lifetime... + | this data with the anonymous lifetime `'_`... | -help: consider changing the `impl Trait`'s explicit `'static` bound +help: consider changing the `impl Trait`'s explicit `'static` bound to the anonymous lifetime `'_` | LL | fn elided2(x: &i32) -> impl Copy + '_ { x } | ^^ @@ -51,9 +51,9 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | ------- ------------------- ^ ...and is captured here | | | | | ...is required to be `'static` by this... - | data with this lifetime... + | this data with lifetime `'a`... | -help: consider changing the `impl Trait`'s explicit `'static` bound +help: consider changing the `impl Trait`'s explicit `'static` bound to lifetime `'a` | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^ @@ -77,9 +77,9 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ------- -------------------------------- ^ ...and is captured here | | | | | ...is required to be `'static` by this... - | data with this lifetime... + | this data with lifetime `'a`... | -help: consider changing the `impl Trait`'s explicit `'static` bound +help: consider changing the `impl Trait`'s explicit `'static` bound to lifetime `'a` | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x } | ^^ @@ -113,9 +113,9 @@ LL | fn elided3(x: &i32) -> Box { Box::new(x) } | | | | | | | ...and is captured here | | ...is required to be `'static` by this... - | data with this lifetime... + | this data with the anonymous lifetime `'_`... | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 18:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn elided3(x: &i32) -> Box { Box::new(x) } | ^^^^ @@ -128,9 +128,9 @@ LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | | | | | | | ...and is captured here | | ...is required to be `'static` by this... - | data with this lifetime... + | this data with lifetime `'a`... | -help: to permit non-static references in a trait object value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 21:14 +help: to permit non-static references in a trait object value, you can add an explicit bound for lifetime `'a` | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^^^ @@ -142,9 +142,10 @@ LL | fn elided4(x: &i32) -> Box { Box::new(x) } | ---- ---------^- | | | | | | | ...and is captured here - | data with this lifetime... ...is required to be `'static` by this... + | | ...is required to be `'static` by this... + | this data with the anonymous lifetime `'_`... | -help: consider changing the trait object's explicit `'static` bound +help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn elided4(x: &i32) -> Box { Box::new(x) } | ^^ @@ -160,9 +161,10 @@ LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } | ------- ---------^- | | | | | | | ...and is captured here - | data with this lifetime... ...is required to be `'static` by this... + | | ...is required to be `'static` by this... + | this data with lifetime `'a`... | -help: consider changing the trait object's explicit `'static` bound +help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^ diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index 1c3a5979ee55b..67d4f60dff6f1 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -4,13 +4,13 @@ error: cannot infer an appropriate lifetime LL | fn iter_values_anon(&self) -> impl Iterator { | ----- ----------------------- ...is required to be `'static` by this... | | - | data with this lifetime... + | this data with the anonymous lifetime `'_`... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | | ...and is captured here | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the method body at 6:5 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ^^^^ @@ -21,13 +21,13 @@ error: cannot infer an appropriate lifetime LL | fn iter_values<'a>(&'a self) -> impl Iterator { | -------- ----------------------- ...is required to be `'static` by this... | | - | data with this lifetime... + | this data with lifetime `'a`... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | | ...and is captured here | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the method body at 10:20 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for lifetime `'a` | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { | ^^^^ diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 038df47e1bd98..c533a72dfc014 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -2,14 +2,14 @@ error: cannot infer an appropriate lifetime --> $DIR/issue-16922.rs:4:14 | LL | fn foo(value: &T) -> Box { - | -- data with this lifetime... + | -- this data with the anonymous lifetime `'_`... LL | Box::new(value) as Box | ---------^^^^^- | | | | | ...and is captured here | ...is required to be `'static` by this... | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn foo(value: &T) -> Box { | ^^^^ diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index 555622c9d13c1..6edef8086b937 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -2,12 +2,12 @@ error: cannot infer an appropriate lifetime --> $DIR/object-lifetime-default-from-box-error.rs:18:5 | LL | fn load(ss: &mut SomeStruct) -> Box { - | --------------- data with this lifetime... + | --------------- this data with the anonymous lifetime `'_`... ... LL | ss.r | ^^^^ ...is captured and required to be `'static` here | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #2 defined on the function body at 14:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn load(ss: &mut SomeStruct) -> Box { | ^^^^ diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 673300cebc26c..4b08c4bff2ebc 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -2,14 +2,14 @@ error: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:8:46 | LL | fn a(v: &[u8]) -> Box { - | ----- data with this lifetime... + | ----- this data with the anonymous lifetime `'_`... LL | let x: Box = Box::new(v); | ---------^- | | | | | ...and is captured here | ...is required to be `'static` by this... | -help: consider changing the trait object's explicit `'static` bound +help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn a(v: &[u8]) -> Box { | ^^ @@ -22,14 +22,14 @@ error: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:13:14 | LL | fn b(v: &[u8]) -> Box { - | ----- data with this lifetime... + | ----- this data with the anonymous lifetime `'_`... LL | Box::new(v) | ---------^- | | | | | ...and is captured here | ...is required to be `'static` by this... | -help: consider changing the trait object's explicit `'static` bound +help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn b(v: &[u8]) -> Box { | ^^ @@ -42,7 +42,7 @@ error: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:19:14 | LL | fn c(v: &[u8]) -> Box { - | ----- data with this lifetime... + | ----- this data with the anonymous lifetime `'_`... ... LL | Box::new(v) | ---------^- @@ -50,7 +50,7 @@ LL | Box::new(v) | | ...and is captured here | ...is required to be `'static` by this... | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 16:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn c(v: &[u8]) -> Box { | ^^^^ diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 982ed07232a80..894be310fd14b 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -2,14 +2,14 @@ error: cannot infer an appropriate lifetime --> $DIR/regions-close-object-into-object-2.rs:10:11 | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { - | ------------------ data with this lifetime... + | ------------------ this data with lifetime `'a`... LL | box B(&*v) as Box | ------^^^--------------- | | | | | ...and is captured here | ...is required to be `'static` by this... | -help: consider changing the trait object's explicit `'static` bound +help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { | ^^ diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index 1b82098ee13c2..ce261d78c2909 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -2,14 +2,14 @@ error: cannot infer an appropriate lifetime --> $DIR/regions-close-object-into-object-4.rs:10:11 | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { - | ---------------- data with this lifetime... + | ---------------- this data with lifetime `'a`... LL | box B(&*v) as Box | ------^^^--------------- | | | | | ...and is captured here | ...is required to be `'static` by this... | -help: consider changing the trait object's explicit `'static` bound +help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { | ^^ diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index e7bbfaababe8a..a0df1815247c3 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -2,7 +2,7 @@ error: cannot infer an appropriate lifetime --> $DIR/regions-proc-bound-capture.rs:9:14 | LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { - | ------ data with this lifetime... + | ------ this data with the anonymous lifetime `'_`... LL | // This is illegal, because the region bound on `proc` is 'static. LL | Box::new(move || { *x }) | ---------^^^^^^^^^^^^^^- @@ -10,7 +10,7 @@ LL | Box::new(move || { *x }) | | ...and is captured here | ...is required to be `'static` by this... | -help: consider changing the trait object's explicit `'static` bound +help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn static_proc(x: &isize) -> Box (isize) + '_> { | ^^ diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 1aeabce5e8aaf..5520341b5b1c3 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -4,7 +4,7 @@ error: cannot infer an appropriate lifetime LL | async fn f(self: Pin<&Self>) -> impl Clone { self } | ^^^^ ---------- ---------- ...and required to be `'static` by this | | | - | | data with this lifetime... + | | this data with the anonymous lifetime `'_`... | ...is captured here... error: aborting due to previous error diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 04c475be787b8..5374929f3a45f 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -5,9 +5,9 @@ LL | fn f(self: Pin<&Self>) -> impl Clone { self } | ---------- ---------- ^^^^ ...and is captured here | | | | | ...is required to be `'static` by this... - | data with this lifetime... + | this data with the anonymous lifetime `'_`... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the method body at 6:5 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } | ^^^^ diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 5cf170d566ca9..471f3cd14aa3e 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -12,14 +12,14 @@ error: cannot infer an appropriate lifetime LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() | ------ ------------- ...is required to be `'static` by this... | | - | data with this lifetime... + | this data with the anonymous lifetime `'_`... ... LL | / move || { LL | | *dest = g.get(); LL | | } | |_____^ ...and is captured here | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 15:1 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ | ^^^^ diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index 4dc4aac6ceac4..5fd03f9770e5d 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -2,12 +2,12 @@ error: cannot infer an appropriate lifetime --> $DIR/dyn-trait-underscore.rs:8:20 | LL | fn a(items: &[T]) -> Box> { - | ---- data with this lifetime... + | ---- this data with the anonymous lifetime `'_`... LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | Box::new(items.iter()) | ---------------^^^^--- ...is captured and required to be `'static` here | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 6:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn a(items: &[T]) -> Box + '_> { | ^^^^ From 50c422e028dd7b66302eabb987fe1da482bee8fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 29 May 2020 19:46:22 -0700 Subject: [PATCH 11/45] Move overlapping span to a note --- .../nice_region_error/static_impl_trait.rs | 31 ++++++++++++- .../must_outlive_least_region_or_bound.stderr | 44 ++++++++++++------- src/test/ui/issues/issue-16922.stderr | 10 +++-- .../region-object-lifetime-in-coercion.stderr | 30 ++++++++----- .../regions-close-object-into-object-2.stderr | 10 +++-- .../regions-close-object-into-object-4.stderr | 10 +++-- .../regions/regions-proc-bound-capture.stderr | 10 +++-- 7 files changed, 99 insertions(+), 46 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index e9f165d309f8f..cc95441b68a03 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -53,7 +53,36 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // Customize the spans and labels depending on their relative order so // that split sentences flow correctly. - if sup_origin.span().shrink_to_hi() <= return_sp.shrink_to_lo() { + if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() { + // Avoid the following: + // + // error: cannot infer an appropriate lifetime + // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 + // | + // LL | fn foo(x: &i32) -> Box { Box::new(x) } + // | ---- ---------^- + // | | | | + // | | | ...and is captured here + // | | ...is required to be `'static` by this... + // | this data with the anonymous lifetime `'_`... + // + // and instead show: + // + // error: cannot infer an appropriate lifetime + // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 + // | + // LL | fn foo(x: &i32) -> Box { Box::new(x) } + // | ---- ^ ...is captured here with a `'static` requirement + // | | + // | this data with the anonymous lifetime `'_`... + // | + // note: ...is required to be `'static` by this + // | + // LL | fn elided3(x: &i32) -> Box { Box::new(x) } + // | ^^^^^^^^^^^ + err.span_label(sup_origin.span(), "...is captured here..."); + err.span_note(return_sp, "...and required to be `'static` by this"); + } else if sup_origin.span() <= return_sp { err.span_label(sup_origin.span(), "...is captured here..."); err.span_label(return_sp, "...and required to be `'static` by this"); } else { diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 00b6ec38323c3..2da49379ea8c2 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -109,12 +109,15 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:18:50 | LL | fn elided3(x: &i32) -> Box { Box::new(x) } - | ---- ---------^- - | | | | - | | | ...and is captured here - | | ...is required to be `'static` by this... + | ---- ^ ...is captured here... + | | | this data with the anonymous lifetime `'_`... | +note: ...and required to be `'static` by this + --> $DIR/must_outlive_least_region_or_bound.rs:18:41 + | +LL | fn elided3(x: &i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^ help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn elided3(x: &i32) -> Box { Box::new(x) } @@ -124,12 +127,15 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:21:59 | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } - | ------- ---------^- - | | | | - | | | ...and is captured here - | | ...is required to be `'static` by this... + | ------- ^ ...is captured here... + | | | this data with lifetime `'a`... | +note: ...and required to be `'static` by this + --> $DIR/must_outlive_least_region_or_bound.rs:21:50 + | +LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^ help: to permit non-static references in a trait object value, you can add an explicit bound for lifetime `'a` | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } @@ -139,12 +145,15 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:24:60 | LL | fn elided4(x: &i32) -> Box { Box::new(x) } - | ---- ---------^- - | | | | - | | | ...and is captured here - | | ...is required to be `'static` by this... + | ---- ^ ...is captured here... + | | | this data with the anonymous lifetime `'_`... | +note: ...and required to be `'static` by this + --> $DIR/must_outlive_least_region_or_bound.rs:24:51 + | +LL | fn elided4(x: &i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn elided4(x: &i32) -> Box { Box::new(x) } @@ -158,12 +167,13 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:27:69 | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ------- ---------^- - | | | | - | | | ...and is captured here - | | ...is required to be `'static` by this... - | this data with lifetime `'a`... + | ------- this data with lifetime `'a`... ^ ...is captured here... | +note: ...and required to be `'static` by this + --> $DIR/must_outlive_least_region_or_bound.rs:27:60 + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index c533a72dfc014..6c0b26a86b651 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -4,11 +4,13 @@ error: cannot infer an appropriate lifetime LL | fn foo(value: &T) -> Box { | -- this data with the anonymous lifetime `'_`... LL | Box::new(value) as Box - | ---------^^^^^- - | | | - | | ...and is captured here - | ...is required to be `'static` by this... + | ^^^^^ ...is captured here... | +note: ...and required to be `'static` by this + --> $DIR/issue-16922.rs:4:5 + | +LL | Box::new(value) as Box + | ^^^^^^^^^^^^^^^ help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn foo(value: &T) -> Box { diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 4b08c4bff2ebc..b333c314c57c9 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -4,11 +4,13 @@ error: cannot infer an appropriate lifetime LL | fn a(v: &[u8]) -> Box { | ----- this data with the anonymous lifetime `'_`... LL | let x: Box = Box::new(v); - | ---------^- - | | | - | | ...and is captured here - | ...is required to be `'static` by this... + | ^ ...is captured here... | +note: ...and required to be `'static` by this + --> $DIR/region-object-lifetime-in-coercion.rs:8:37 + | +LL | let x: Box = Box::new(v); + | ^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn a(v: &[u8]) -> Box { @@ -24,11 +26,13 @@ error: cannot infer an appropriate lifetime LL | fn b(v: &[u8]) -> Box { | ----- this data with the anonymous lifetime `'_`... LL | Box::new(v) - | ---------^- - | | | - | | ...and is captured here - | ...is required to be `'static` by this... + | ^ ...is captured here... | +note: ...and required to be `'static` by this + --> $DIR/region-object-lifetime-in-coercion.rs:13:5 + | +LL | Box::new(v) + | ^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn b(v: &[u8]) -> Box { @@ -45,11 +49,13 @@ LL | fn c(v: &[u8]) -> Box { | ----- this data with the anonymous lifetime `'_`... ... LL | Box::new(v) - | ---------^- - | | | - | | ...and is captured here - | ...is required to be `'static` by this... + | ^ ...is captured here... + | +note: ...and required to be `'static` by this + --> $DIR/region-object-lifetime-in-coercion.rs:19:5 | +LL | Box::new(v) + | ^^^^^^^^^^^ help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn c(v: &[u8]) -> Box { diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 894be310fd14b..3127ae65ace7d 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -4,11 +4,13 @@ error: cannot infer an appropriate lifetime LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { | ------------------ this data with lifetime `'a`... LL | box B(&*v) as Box - | ------^^^--------------- - | | | - | | ...and is captured here - | ...is required to be `'static` by this... + | ^^^ ...is captured here... | +note: ...and required to be `'static` by this + --> $DIR/regions-close-object-into-object-2.rs:10:5 + | +LL | box B(&*v) as Box + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index ce261d78c2909..b18c61f137694 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -4,11 +4,13 @@ error: cannot infer an appropriate lifetime LL | fn i<'a, T, U>(v: Box+'a>) -> Box { | ---------------- this data with lifetime `'a`... LL | box B(&*v) as Box - | ------^^^--------------- - | | | - | | ...and is captured here - | ...is required to be `'static` by this... + | ^^^ ...is captured here... | +note: ...and required to be `'static` by this + --> $DIR/regions-close-object-into-object-4.rs:10:5 + | +LL | box B(&*v) as Box + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index a0df1815247c3..5cb9506afd351 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -5,11 +5,13 @@ LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { | ------ this data with the anonymous lifetime `'_`... LL | // This is illegal, because the region bound on `proc` is 'static. LL | Box::new(move || { *x }) - | ---------^^^^^^^^^^^^^^- - | | | - | | ...and is captured here - | ...is required to be `'static` by this... + | ^^^^^^^^^^^^^^ ...is captured here... | +note: ...and required to be `'static` by this + --> $DIR/regions-proc-bound-capture.rs:9:5 + | +LL | Box::new(move || { *x }) + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn static_proc(x: &isize) -> Box (isize) + '_> { From 17951e21d4c690ad70e79a40d223a0d0984c0f35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 30 May 2020 09:54:05 -0700 Subject: [PATCH 12/45] Tweak output for overlapping required/captured spans --- .../nice_region_error/static_impl_trait.rs | 10 +++---- .../must_outlive_least_region_or_bound.stderr | 28 +++---------------- src/test/ui/issues/issue-16922.stderr | 7 +---- .../region-object-lifetime-in-coercion.stderr | 21 ++------------ .../regions-close-object-into-object-2.stderr | 7 +---- .../regions-close-object-into-object-4.stderr | 7 +---- .../regions/regions-proc-bound-capture.stderr | 7 +---- 7 files changed, 15 insertions(+), 72 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index cc95441b68a03..253057536f133 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -76,12 +76,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // | | // | this data with the anonymous lifetime `'_`... // | - // note: ...is required to be `'static` by this - // | - // LL | fn elided3(x: &i32) -> Box { Box::new(x) } - // | ^^^^^^^^^^^ - err.span_label(sup_origin.span(), "...is captured here..."); - err.span_note(return_sp, "...and required to be `'static` by this"); + err.span_label( + sup_origin.span(), + "...is captured here with a `'static` requirement", + ); } else if sup_origin.span() <= return_sp { err.span_label(sup_origin.span(), "...is captured here..."); err.span_label(return_sp, "...and required to be `'static` by this"); diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 2da49379ea8c2..82e44cff9cc44 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -109,15 +109,10 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:18:50 | LL | fn elided3(x: &i32) -> Box { Box::new(x) } - | ---- ^ ...is captured here... + | ---- ^ ...is captured here with a `'static` requirement | | | this data with the anonymous lifetime `'_`... | -note: ...and required to be `'static` by this - --> $DIR/must_outlive_least_region_or_bound.rs:18:41 - | -LL | fn elided3(x: &i32) -> Box { Box::new(x) } - | ^^^^^^^^^^^ help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn elided3(x: &i32) -> Box { Box::new(x) } @@ -127,15 +122,10 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:21:59 | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } - | ------- ^ ...is captured here... + | ------- ^ ...is captured here with a `'static` requirement | | | this data with lifetime `'a`... | -note: ...and required to be `'static` by this - --> $DIR/must_outlive_least_region_or_bound.rs:21:50 - | -LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } - | ^^^^^^^^^^^ help: to permit non-static references in a trait object value, you can add an explicit bound for lifetime `'a` | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } @@ -145,15 +135,10 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:24:60 | LL | fn elided4(x: &i32) -> Box { Box::new(x) } - | ---- ^ ...is captured here... + | ---- ^ ...is captured here with a `'static` requirement | | | this data with the anonymous lifetime `'_`... | -note: ...and required to be `'static` by this - --> $DIR/must_outlive_least_region_or_bound.rs:24:51 - | -LL | fn elided4(x: &i32) -> Box { Box::new(x) } - | ^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn elided4(x: &i32) -> Box { Box::new(x) } @@ -167,13 +152,8 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:27:69 | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ------- this data with lifetime `'a`... ^ ...is captured here... + | ------- this data with lifetime `'a`... ^ ...is captured here with a `'static` requirement | -note: ...and required to be `'static` by this - --> $DIR/must_outlive_least_region_or_bound.rs:27:60 - | -LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 6c0b26a86b651..a254343cd1bb7 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -4,13 +4,8 @@ error: cannot infer an appropriate lifetime LL | fn foo(value: &T) -> Box { | -- this data with the anonymous lifetime `'_`... LL | Box::new(value) as Box - | ^^^^^ ...is captured here... + | ^^^^^ ...is captured here with a `'static` requirement | -note: ...and required to be `'static` by this - --> $DIR/issue-16922.rs:4:5 - | -LL | Box::new(value) as Box - | ^^^^^^^^^^^^^^^ help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn foo(value: &T) -> Box { diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index b333c314c57c9..97d1f3579fcd8 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -4,13 +4,8 @@ error: cannot infer an appropriate lifetime LL | fn a(v: &[u8]) -> Box { | ----- this data with the anonymous lifetime `'_`... LL | let x: Box = Box::new(v); - | ^ ...is captured here... + | ^ ...is captured here with a `'static` requirement | -note: ...and required to be `'static` by this - --> $DIR/region-object-lifetime-in-coercion.rs:8:37 - | -LL | let x: Box = Box::new(v); - | ^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn a(v: &[u8]) -> Box { @@ -26,13 +21,8 @@ error: cannot infer an appropriate lifetime LL | fn b(v: &[u8]) -> Box { | ----- this data with the anonymous lifetime `'_`... LL | Box::new(v) - | ^ ...is captured here... + | ^ ...is captured here with a `'static` requirement | -note: ...and required to be `'static` by this - --> $DIR/region-object-lifetime-in-coercion.rs:13:5 - | -LL | Box::new(v) - | ^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn b(v: &[u8]) -> Box { @@ -49,13 +39,8 @@ LL | fn c(v: &[u8]) -> Box { | ----- this data with the anonymous lifetime `'_`... ... LL | Box::new(v) - | ^ ...is captured here... - | -note: ...and required to be `'static` by this - --> $DIR/region-object-lifetime-in-coercion.rs:19:5 + | ^ ...is captured here with a `'static` requirement | -LL | Box::new(v) - | ^^^^^^^^^^^ help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn c(v: &[u8]) -> Box { diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 3127ae65ace7d..3d707f2d99941 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -4,13 +4,8 @@ error: cannot infer an appropriate lifetime LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { | ------------------ this data with lifetime `'a`... LL | box B(&*v) as Box - | ^^^ ...is captured here... + | ^^^ ...is captured here with a `'static` requirement | -note: ...and required to be `'static` by this - --> $DIR/regions-close-object-into-object-2.rs:10:5 - | -LL | box B(&*v) as Box - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index b18c61f137694..70282c8cbdb30 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -4,13 +4,8 @@ error: cannot infer an appropriate lifetime LL | fn i<'a, T, U>(v: Box+'a>) -> Box { | ---------------- this data with lifetime `'a`... LL | box B(&*v) as Box - | ^^^ ...is captured here... + | ^^^ ...is captured here with a `'static` requirement | -note: ...and required to be `'static` by this - --> $DIR/regions-close-object-into-object-4.rs:10:5 - | -LL | box B(&*v) as Box - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index 5cb9506afd351..8f93fad7fe9d8 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -5,13 +5,8 @@ LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { | ------ this data with the anonymous lifetime `'_`... LL | // This is illegal, because the region bound on `proc` is 'static. LL | Box::new(move || { *x }) - | ^^^^^^^^^^^^^^ ...is captured here... + | ^^^^^^^^^^^^^^ ...is captured here with a `'static` requirement | -note: ...and required to be `'static` by this - --> $DIR/regions-proc-bound-capture.rs:9:5 - | -LL | Box::new(move || { *x }) - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn static_proc(x: &isize) -> Box (isize) + '_> { From 19bb589410f2ab0ff14178992ef4b44fbe5e297b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 30 May 2020 10:15:58 -0700 Subject: [PATCH 13/45] Tweak wording and add error code --- .../nice_region_error/static_impl_trait.rs | 35 +++++++------ .../ui/async-await/issues/issue-62097.stderr | 6 +-- .../must_outlive_least_region_or_bound.stderr | 52 +++++++++---------- .../static-return-lifetime-infered.stderr | 12 ++--- src/test/ui/issues/issue-16922.stderr | 8 +-- ...ect-lifetime-default-from-box-error.stderr | 8 +-- .../region-object-lifetime-in-coercion.stderr | 24 ++++----- .../regions-close-object-into-object-2.stderr | 4 +- .../regions-close-object-into-object-4.stderr | 4 +- .../regions/regions-proc-bound-capture.stderr | 8 +-- ...types_pin_lifetime_impl_trait-async.stderr | 6 +-- ..._self_types_pin_lifetime_impl_trait.stderr | 8 +-- .../missing-lifetimes-in-signature.stderr | 8 +-- .../dyn-trait-underscore.stderr | 8 +-- 14 files changed, 97 insertions(+), 94 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 253057536f133..4e16e8c2c5717 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -2,7 +2,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; -use rustc_errors::{Applicability, ErrorReported}; +use rustc_errors::{struct_span_err, Applicability, ErrorReported}; use rustc_hir::{GenericBound, ItemKind, Lifetime, LifetimeName, TyKind}; use rustc_middle::ty::RegionKind; @@ -35,10 +35,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let (lifetime_name, lifetime) = if sup_r.has_name() { (sup_r.to_string(), format!("lifetime `{}`", sup_r)) } else { - ("'_".to_owned(), "the anonymous lifetime `'_`".to_string()) + ("'_".to_owned(), "an anonymous lifetime `'_`".to_string()) }; - let mut err = - self.tcx().sess.struct_span_err(sp, "cannot infer an appropriate lifetime"); + let mut err = struct_span_err!( + self.tcx().sess, + sp, + E0758, + "cannot infer an appropriate lifetime" + ); err.span_label( param_info.param_ty_span, &format!("this data with {}...", lifetime), @@ -61,10 +65,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // | // LL | fn foo(x: &i32) -> Box { Box::new(x) } // | ---- ---------^- - // | | | | - // | | | ...and is captured here - // | | ...is required to be `'static` by this... - // | this data with the anonymous lifetime `'_`... // // and instead show: // @@ -72,25 +72,28 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 // | // LL | fn foo(x: &i32) -> Box { Box::new(x) } - // | ---- ^ ...is captured here with a `'static` requirement - // | | - // | this data with the anonymous lifetime `'_`... - // | + // | ---- ^ err.span_label( sup_origin.span(), - "...is captured here with a `'static` requirement", + "...is captured here requiring it to live as long as `'static`", ); } else if sup_origin.span() <= return_sp { err.span_label(sup_origin.span(), "...is captured here..."); - err.span_label(return_sp, "...and required to be `'static` by this"); + err.span_label( + return_sp, + "...and required to live as long as `'static` by this", + ); } else { - err.span_label(return_sp, "...is required to be `'static` by this..."); + err.span_label( + return_sp, + "...is required to live as long as `'static` by this...", + ); err.span_label(sup_origin.span(), "...and is captured here"); } } else { err.span_label( return_sp, - "...is captured and required to be `'static` here", + "...is captured and required live as long as `'static` here", ); } diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index fff43ae9f47bc..558d89f928945 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -1,13 +1,13 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/issue-62097.rs:12:31 | LL | pub async fn run_dummy_fn(&self) { | ^^^^^ | | - | this data with the anonymous lifetime `'_`... + | this data with an anonymous lifetime `'_`... | ...is captured here... LL | foo(|| self.bar()).await; - | --- ...and required to be `'static` by this + | --- ...and required to live as long as `'static` by this error: aborting due to previous error diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 82e44cff9cc44..eff56ddc440d4 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -1,24 +1,24 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:3:35 | LL | fn elided(x: &i32) -> impl Copy { x } | ---- --------- ^ ...and is captured here | | | - | | ...is required to be `'static` by this... - | this data with the anonymous lifetime `'_`... + | | ...is required to live as long as `'static` by this... + | this data with an anonymous lifetime `'_`... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:6:44 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | ------- --------- ^ ...and is captured here | | | - | | ...is required to be `'static` by this... + | | ...is required to live as long as `'static` by this... | this data with lifetime `'a`... | help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for lifetime `'a` @@ -26,16 +26,16 @@ help: to permit non-static references in an `impl Trait` value, you can add an e LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:9:46 | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | ---- ------------------- ^ ...and is captured here | | | - | | ...is required to be `'static` by this... - | this data with the anonymous lifetime `'_`... + | | ...is required to live as long as `'static` by this... + | this data with an anonymous lifetime `'_`... | -help: consider changing the `impl Trait`'s explicit `'static` bound to the anonymous lifetime `'_` +help: consider changing the `impl Trait`'s explicit `'static` bound to an anonymous lifetime `'_` | LL | fn elided2(x: &i32) -> impl Copy + '_ { x } | ^^ @@ -44,13 +44,13 @@ help: alternatively, set an explicit `'static` lifetime to this parameter LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:12:55 | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | ------- ------------------- ^ ...and is captured here | | | - | | ...is required to be `'static` by this... + | | ...is required to live as long as `'static` by this... | this data with lifetime `'a`... | help: consider changing the `impl Trait`'s explicit `'static` bound to lifetime `'a` @@ -70,13 +70,13 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | | | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:33:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ------- -------------------------------- ^ ...and is captured here | | | - | | ...is required to be `'static` by this... + | | ...is required to live as long as `'static` by this... | this data with lifetime `'a`... | help: consider changing the `impl Trait`'s explicit `'static` bound to lifetime `'a` @@ -105,24 +105,24 @@ LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | | | help: consider adding an explicit lifetime bound...: `T: 'static +` -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:18:50 | LL | fn elided3(x: &i32) -> Box { Box::new(x) } - | ---- ^ ...is captured here with a `'static` requirement + | ---- ^ ...is captured here requiring it to live as long as `'static` | | - | this data with the anonymous lifetime `'_`... + | this data with an anonymous lifetime `'_`... | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn elided3(x: &i32) -> Box { Box::new(x) } | ^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:21:59 | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } - | ------- ^ ...is captured here with a `'static` requirement + | ------- ^ ...is captured here requiring it to live as long as `'static` | | | this data with lifetime `'a`... | @@ -131,15 +131,15 @@ help: to permit non-static references in a trait object value, you can add an ex LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:24:60 | LL | fn elided4(x: &i32) -> Box { Box::new(x) } - | ---- ^ ...is captured here with a `'static` requirement + | ---- ^ ...is captured here requiring it to live as long as `'static` | | - | this data with the anonymous lifetime `'_`... + | this data with an anonymous lifetime `'_`... | -help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` +help: consider changing the trait object's explicit `'static` bound to an anonymous lifetime `'_` | LL | fn elided4(x: &i32) -> Box { Box::new(x) } | ^^ @@ -148,11 +148,11 @@ help: alternatively, set an explicit `'static` lifetime in this parameter LL | fn elided4(x: &'static i32) -> Box { Box::new(x) } | ^^^^^^^^^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:27:69 | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ------- this data with lifetime `'a`... ^ ...is captured here with a `'static` requirement + | ------- this data with lifetime `'a`... ^ ...is captured here requiring it to live as long as `'static` | help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index 67d4f60dff6f1..a48580ee2d2fc 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -1,25 +1,25 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:7:16 | LL | fn iter_values_anon(&self) -> impl Iterator { - | ----- ----------------------- ...is required to be `'static` by this... + | ----- ----------------------- ...is required to live as long as `'static` by this... | | - | this data with the anonymous lifetime `'_`... + | this data with an anonymous lifetime `'_`... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | | ...and is captured here | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:11:16 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | -------- ----------------------- ...is required to be `'static` by this... + | -------- ----------------------- ...is required to live as long as `'static` by this... | | | this data with lifetime `'a`... LL | self.x.iter().map(|a| a.0) diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index a254343cd1bb7..53fd658800a7a 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -1,12 +1,12 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/issue-16922.rs:4:14 | LL | fn foo(value: &T) -> Box { - | -- this data with the anonymous lifetime `'_`... + | -- this data with an anonymous lifetime `'_`... LL | Box::new(value) as Box - | ^^^^^ ...is captured here with a `'static` requirement + | ^^^^^ ...is captured here requiring it to live as long as `'static` | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn foo(value: &T) -> Box { | ^^^^ diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index 6edef8086b937..04a06104faf99 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -1,13 +1,13 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/object-lifetime-default-from-box-error.rs:18:5 | LL | fn load(ss: &mut SomeStruct) -> Box { - | --------------- this data with the anonymous lifetime `'_`... + | --------------- this data with an anonymous lifetime `'_`... ... LL | ss.r - | ^^^^ ...is captured and required to be `'static` here + | ^^^^ ...is captured and required live as long as `'static` here | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn load(ss: &mut SomeStruct) -> Box { | ^^^^ diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 97d1f3579fcd8..34cf131319a1c 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -1,12 +1,12 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:8:46 | LL | fn a(v: &[u8]) -> Box { - | ----- this data with the anonymous lifetime `'_`... + | ----- this data with an anonymous lifetime `'_`... LL | let x: Box = Box::new(v); - | ^ ...is captured here with a `'static` requirement + | ^ ...is captured here requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` +help: consider changing the trait object's explicit `'static` bound to an anonymous lifetime `'_` | LL | fn a(v: &[u8]) -> Box { | ^^ @@ -15,15 +15,15 @@ help: alternatively, set an explicit `'static` lifetime in this parameter LL | fn a(v: &'static [u8]) -> Box { | ^^^^^^^^^^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:13:14 | LL | fn b(v: &[u8]) -> Box { - | ----- this data with the anonymous lifetime `'_`... + | ----- this data with an anonymous lifetime `'_`... LL | Box::new(v) - | ^ ...is captured here with a `'static` requirement + | ^ ...is captured here requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` +help: consider changing the trait object's explicit `'static` bound to an anonymous lifetime `'_` | LL | fn b(v: &[u8]) -> Box { | ^^ @@ -32,16 +32,16 @@ help: alternatively, set an explicit `'static` lifetime in this parameter LL | fn b(v: &'static [u8]) -> Box { | ^^^^^^^^^^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:19:14 | LL | fn c(v: &[u8]) -> Box { - | ----- this data with the anonymous lifetime `'_`... + | ----- this data with an anonymous lifetime `'_`... ... LL | Box::new(v) - | ^ ...is captured here with a `'static` requirement + | ^ ...is captured here requiring it to live as long as `'static` | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn c(v: &[u8]) -> Box { | ^^^^ diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 3d707f2d99941..be47ef589af8c 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -1,10 +1,10 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/regions-close-object-into-object-2.rs:10:11 | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { | ------------------ this data with lifetime `'a`... LL | box B(&*v) as Box - | ^^^ ...is captured here with a `'static` requirement + | ^^^ ...is captured here requiring it to live as long as `'static` | help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index 70282c8cbdb30..1b099c7d8bdf0 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -1,10 +1,10 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/regions-close-object-into-object-4.rs:10:11 | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { | ---------------- this data with lifetime `'a`... LL | box B(&*v) as Box - | ^^^ ...is captured here with a `'static` requirement + | ^^^ ...is captured here requiring it to live as long as `'static` | help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index 8f93fad7fe9d8..e8baf44bd10aa 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -1,13 +1,13 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/regions-proc-bound-capture.rs:9:14 | LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { - | ------ this data with the anonymous lifetime `'_`... + | ------ this data with an anonymous lifetime `'_`... LL | // This is illegal, because the region bound on `proc` is 'static. LL | Box::new(move || { *x }) - | ^^^^^^^^^^^^^^ ...is captured here with a `'static` requirement + | ^^^^^^^^^^^^^^ ...is captured here requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` +help: consider changing the trait object's explicit `'static` bound to an anonymous lifetime `'_` | LL | fn static_proc(x: &isize) -> Box (isize) + '_> { | ^^ diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 5520341b5b1c3..92e1473a5da73 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -1,10 +1,10 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^ ---------- ---------- ...and required to be `'static` by this + | ^^^^ ---------- ---------- ...and required to live as long as `'static` by this | | | - | | this data with the anonymous lifetime `'_`... + | | this data with an anonymous lifetime `'_`... | ...is captured here... error: aborting due to previous error diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 5374929f3a45f..6721d41bb73c9 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -1,13 +1,13 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44 | LL | fn f(self: Pin<&Self>) -> impl Clone { self } | ---------- ---------- ^^^^ ...and is captured here | | | - | | ...is required to be `'static` by this... - | this data with the anonymous lifetime `'_`... + | | ...is required to live as long as `'static` by this... + | this data with an anonymous lifetime `'_`... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } | ^^^^ diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 471f3cd14aa3e..ba56255af5b0c 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -6,20 +6,20 @@ LL | fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ | | | help: consider introducing lifetime `'a` here: `'a,` -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/missing-lifetimes-in-signature.rs:19:5 | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() - | ------ ------------- ...is required to be `'static` by this... + | ------ ------------- ...is required to live as long as `'static` by this... | | - | this data with the anonymous lifetime `'_`... + | this data with an anonymous lifetime `'_`... ... LL | / move || { LL | | *dest = g.get(); LL | | } | |_____^ ...and is captured here | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ | ^^^^ diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index 5fd03f9770e5d..20d3640d4118e 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -1,13 +1,13 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/dyn-trait-underscore.rs:8:20 | LL | fn a(items: &[T]) -> Box> { - | ---- this data with the anonymous lifetime `'_`... + | ---- this data with an anonymous lifetime `'_`... LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | Box::new(items.iter()) - | ---------------^^^^--- ...is captured and required to be `'static` here + | ---------------^^^^--- ...is captured and required live as long as `'static` here | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn a(items: &[T]) -> Box + '_> { | ^^^^ From 3cfecdee0d677e0982cd160991130a997ffc619e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 1 Jun 2020 16:15:10 -0700 Subject: [PATCH 14/45] review comments: wording --- .../nice_region_error/static_impl_trait.rs | 58 ++++++++++--------- .../ui/async-await/issues/issue-62097.stderr | 2 +- .../must_outlive_least_region_or_bound.stderr | 46 +++++++-------- .../static-return-lifetime-infered.stderr | 8 +-- src/test/ui/issues/issue-16922.stderr | 4 +- ...ect-lifetime-default-from-box-error.stderr | 2 +- .../region-object-lifetime-in-coercion.stderr | 16 ++--- .../regions-close-object-into-object-2.stderr | 6 +- .../regions-close-object-into-object-4.stderr | 6 +- .../regions/regions-proc-bound-capture.stderr | 6 +- ...types_pin_lifetime_impl_trait-async.stderr | 2 +- ..._self_types_pin_lifetime_impl_trait.stderr | 4 +- .../missing-lifetimes-in-signature.stderr | 4 +- .../dyn-trait-underscore.stderr | 2 +- 14 files changed, 85 insertions(+), 81 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 4e16e8c2c5717..86f310eb71d76 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -75,18 +75,18 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // | ---- ^ err.span_label( sup_origin.span(), - "...is captured here requiring it to live as long as `'static`", + "...is captured here, requiring it to live as long as `'static`", ); } else if sup_origin.span() <= return_sp { err.span_label(sup_origin.span(), "...is captured here..."); err.span_label( return_sp, - "...and required to live as long as `'static` by this", + "...and is required to live as long as `'static` here", ); } else { err.span_label( return_sp, - "...is required to live as long as `'static` by this...", + "...is required to live as long as `'static` here...", ); err.span_label(sup_origin.span(), "...and is captured here"); } @@ -101,6 +101,20 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // explicit non-desugar'able return. if fn_return.span.desugaring_kind().is_none() { // FIXME: account for the need of parens in `&(dyn Trait + '_)` + + let consider = "consider changing the"; + let declare = "to declare that the"; + let arg = match param_info.param.pat.simple_ident() { + Some(simple_ident) => format!("argument `{}`", simple_ident), + None => "the argument".to_string(), + }; + let explicit = + format!("you can add an explicit `{}` lifetime bound", lifetime_name); + let explicit_static = format!("explicit `'static` bound to {}", arg); + let captures = format!("captures data from {}", arg); + let add_static_bound = + "alternatively, add an explicit `'static` bound to this reference"; + let plus_lt = format!(" + {}", lifetime_name); match fn_return.kind { TyKind::Def(item_id, _) => { let item = self.tcx().hir().item(item_id.id); @@ -126,18 +140,13 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { { err.span_suggestion_verbose( span, - &format!( - "consider changing the `impl Trait`'s explicit \ - `'static` bound to {}", - lifetime, - ), + &format!("{} `impl Trait`'s {}", consider, explicit_static), lifetime_name, Applicability::MaybeIncorrect, ); err.span_suggestion_verbose( param_info.param_ty_span, - "alternatively, set an explicit `'static` lifetime to \ - this parameter", + add_static_bound, param_info.param_ty.to_string(), Applicability::MaybeIncorrect, ); @@ -145,11 +154,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), &format!( - "to permit non-static references in an `impl Trait` \ - value, you can add an explicit bound for {}", - lifetime, + "{declare} `impl Trait` {captures}, {explicit}", + declare = declare, + captures = captures, + explicit = explicit, ), - format!(" + {}", lifetime_name), + plus_lt, Applicability::MaybeIncorrect, ); }; @@ -159,31 +169,25 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), &format!( - "to permit non-static references in a trait object \ - value, you can add an explicit bound for {}", - lifetime, + "{declare} trait object {captures}, {explicit}", + declare = declare, + captures = captures, + explicit = explicit, ), - format!(" + {}", lifetime_name), + plus_lt, Applicability::MaybeIncorrect, ); } _ => { err.span_suggestion_verbose( lt.span, - &format!( - "consider changing the trait object's explicit \ - `'static` bound to {}", - lifetime, - ), + &format!("{} trait object's {}", consider, explicit_static), lifetime_name, Applicability::MaybeIncorrect, ); err.span_suggestion_verbose( param_info.param_ty_span, - &format!( - "alternatively, set an explicit `'static` lifetime \ - in this parameter", - ), + add_static_bound, param_info.param_ty.to_string(), Applicability::MaybeIncorrect, ); diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index 558d89f928945..e9f155c6ced31 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -7,7 +7,7 @@ LL | pub async fn run_dummy_fn(&self) { | this data with an anonymous lifetime `'_`... | ...is captured here... LL | foo(|| self.bar()).await; - | --- ...and required to live as long as `'static` by this + | --- ...and is required to live as long as `'static` here error: aborting due to previous error diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index eff56ddc440d4..a9fa0e93fed61 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -4,10 +4,10 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn elided(x: &i32) -> impl Copy { x } | ---- --------- ^ ...and is captured here | | | - | | ...is required to live as long as `'static` by this... + | | ...is required to live as long as `'static` here... | this data with an anonymous lifetime `'_`... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound | LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ^^^^ @@ -18,10 +18,10 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | ------- --------- ^ ...and is captured here | | | - | | ...is required to live as long as `'static` by this... + | | ...is required to live as long as `'static` here... | this data with lifetime `'a`... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for lifetime `'a` +help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'a` lifetime bound | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^ @@ -32,14 +32,14 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | ---- ------------------- ^ ...and is captured here | | | - | | ...is required to live as long as `'static` by this... + | | ...is required to live as long as `'static` here... | this data with an anonymous lifetime `'_`... | -help: consider changing the `impl Trait`'s explicit `'static` bound to an anonymous lifetime `'_` +help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` | LL | fn elided2(x: &i32) -> impl Copy + '_ { x } | ^^ -help: alternatively, set an explicit `'static` lifetime to this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^ @@ -50,14 +50,14 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | ------- ------------------- ^ ...and is captured here | | | - | | ...is required to live as long as `'static` by this... + | | ...is required to live as long as `'static` here... | this data with lifetime `'a`... | -help: consider changing the `impl Trait`'s explicit `'static` bound to lifetime `'a` +help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^ -help: alternatively, set an explicit `'static` lifetime to this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^ @@ -76,14 +76,14 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ------- -------------------------------- ^ ...and is captured here | | | - | | ...is required to live as long as `'static` by this... + | | ...is required to live as long as `'static` here... | this data with lifetime `'a`... | -help: consider changing the `impl Trait`'s explicit `'static` bound to lifetime `'a` +help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x } | ^^ -help: alternatively, set an explicit `'static` lifetime to this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x } | ^^^^^^^^^^^^ @@ -109,11 +109,11 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:18:50 | LL | fn elided3(x: &i32) -> Box { Box::new(x) } - | ---- ^ ...is captured here requiring it to live as long as `'static` + | ---- ^ ...is captured here, requiring it to live as long as `'static` | | | this data with an anonymous lifetime `'_`... | -help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound | LL | fn elided3(x: &i32) -> Box { Box::new(x) } | ^^^^ @@ -122,11 +122,11 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:21:59 | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } - | ------- ^ ...is captured here requiring it to live as long as `'static` + | ------- ^ ...is captured here, requiring it to live as long as `'static` | | | this data with lifetime `'a`... | -help: to permit non-static references in a trait object value, you can add an explicit bound for lifetime `'a` +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'a` lifetime bound | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^^^ @@ -135,15 +135,15 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:24:60 | LL | fn elided4(x: &i32) -> Box { Box::new(x) } - | ---- ^ ...is captured here requiring it to live as long as `'static` + | ---- ^ ...is captured here, requiring it to live as long as `'static` | | | this data with an anonymous lifetime `'_`... | -help: consider changing the trait object's explicit `'static` bound to an anonymous lifetime `'_` +help: consider changing the trait object's explicit `'static` bound to argument `x` | LL | fn elided4(x: &i32) -> Box { Box::new(x) } | ^^ -help: alternatively, set an explicit `'static` lifetime in this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn elided4(x: &'static i32) -> Box { Box::new(x) } | ^^^^^^^^^^^^ @@ -152,13 +152,13 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:27:69 | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ------- this data with lifetime `'a`... ^ ...is captured here requiring it to live as long as `'static` + | ------- this data with lifetime `'a`... ^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to lifetime `'a` +help: consider changing the trait object's explicit `'static` bound to argument `x` | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^ -help: alternatively, set an explicit `'static` lifetime in this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn explicit4<'a>(x: &'static i32) -> Box { Box::new(x) } | ^^^^^^^^^^^^ diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index a48580ee2d2fc..6681eaa909ee0 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -2,7 +2,7 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:7:16 | LL | fn iter_values_anon(&self) -> impl Iterator { - | ----- ----------------------- ...is required to live as long as `'static` by this... + | ----- ----------------------- ...is required to live as long as `'static` here... | | | this data with an anonymous lifetime `'_`... LL | self.x.iter().map(|a| a.0) @@ -10,7 +10,7 @@ LL | self.x.iter().map(|a| a.0) | | | ...and is captured here | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ^^^^ @@ -19,7 +19,7 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:11:16 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | -------- ----------------------- ...is required to live as long as `'static` by this... + | -------- ----------------------- ...is required to live as long as `'static` here... | | | this data with lifetime `'a`... LL | self.x.iter().map(|a| a.0) @@ -27,7 +27,7 @@ LL | self.x.iter().map(|a| a.0) | | | ...and is captured here | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for lifetime `'a` +help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { | ^^^^ diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 53fd658800a7a..95f46bd7f3eb6 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -4,9 +4,9 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn foo(value: &T) -> Box { | -- this data with an anonymous lifetime `'_`... LL | Box::new(value) as Box - | ^^^^^ ...is captured here requiring it to live as long as `'static` + | ^^^^^ ...is captured here, requiring it to live as long as `'static` | -help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the trait object captures data from argument `value`, you can add an explicit `'_` lifetime bound | LL | fn foo(value: &T) -> Box { | ^^^^ diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index 04a06104faf99..e585db262f2d8 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -7,7 +7,7 @@ LL | fn load(ss: &mut SomeStruct) -> Box { LL | ss.r | ^^^^ ...is captured and required live as long as `'static` here | -help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the trait object captures data from argument `ss`, you can add an explicit `'_` lifetime bound | LL | fn load(ss: &mut SomeStruct) -> Box { | ^^^^ diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 34cf131319a1c..8d048d90cb345 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -4,13 +4,13 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn a(v: &[u8]) -> Box { | ----- this data with an anonymous lifetime `'_`... LL | let x: Box = Box::new(v); - | ^ ...is captured here requiring it to live as long as `'static` + | ^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to an anonymous lifetime `'_` +help: consider changing the trait object's explicit `'static` bound to argument `v` | LL | fn a(v: &[u8]) -> Box { | ^^ -help: alternatively, set an explicit `'static` lifetime in this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn a(v: &'static [u8]) -> Box { | ^^^^^^^^^^^^^ @@ -21,13 +21,13 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn b(v: &[u8]) -> Box { | ----- this data with an anonymous lifetime `'_`... LL | Box::new(v) - | ^ ...is captured here requiring it to live as long as `'static` + | ^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to an anonymous lifetime `'_` +help: consider changing the trait object's explicit `'static` bound to argument `v` | LL | fn b(v: &[u8]) -> Box { | ^^ -help: alternatively, set an explicit `'static` lifetime in this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn b(v: &'static [u8]) -> Box { | ^^^^^^^^^^^^^ @@ -39,9 +39,9 @@ LL | fn c(v: &[u8]) -> Box { | ----- this data with an anonymous lifetime `'_`... ... LL | Box::new(v) - | ^ ...is captured here requiring it to live as long as `'static` + | ^ ...is captured here, requiring it to live as long as `'static` | -help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the trait object captures data from argument `v`, you can add an explicit `'_` lifetime bound | LL | fn c(v: &[u8]) -> Box { | ^^^^ diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index be47ef589af8c..5dfe384112b2a 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -4,13 +4,13 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { | ------------------ this data with lifetime `'a`... LL | box B(&*v) as Box - | ^^^ ...is captured here requiring it to live as long as `'static` + | ^^^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to lifetime `'a` +help: consider changing the trait object's explicit `'static` bound to argument `v` | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { | ^^ -help: alternatively, set an explicit `'static` lifetime in this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn g<'a, T: 'static>(v: std::boxed::Box<(dyn A + 'static)>) -> Box { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index 1b099c7d8bdf0..4d23118ba06f0 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -4,13 +4,13 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn i<'a, T, U>(v: Box+'a>) -> Box { | ---------------- this data with lifetime `'a`... LL | box B(&*v) as Box - | ^^^ ...is captured here requiring it to live as long as `'static` + | ^^^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to lifetime `'a` +help: consider changing the trait object's explicit `'static` bound to argument `v` | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { | ^^ -help: alternatively, set an explicit `'static` lifetime in this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn i<'a, T, U>(v: std::boxed::Box<(dyn A + 'static)>) -> Box { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index e8baf44bd10aa..e36f77ec1da96 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -5,13 +5,13 @@ LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { | ------ this data with an anonymous lifetime `'_`... LL | // This is illegal, because the region bound on `proc` is 'static. LL | Box::new(move || { *x }) - | ^^^^^^^^^^^^^^ ...is captured here requiring it to live as long as `'static` + | ^^^^^^^^^^^^^^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to an anonymous lifetime `'_` +help: consider changing the trait object's explicit `'static` bound to argument `x` | LL | fn static_proc(x: &isize) -> Box (isize) + '_> { | ^^ -help: alternatively, set an explicit `'static` lifetime in this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn static_proc(x: &'static isize) -> Box (isize) + 'static> { | ^^^^^^^^^^^^^^ diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 92e1473a5da73..365e38515b12c 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -2,7 +2,7 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^ ---------- ---------- ...and required to live as long as `'static` by this + | ^^^^ ---------- ---------- ...and is required to live as long as `'static` here | | | | | this data with an anonymous lifetime `'_`... | ...is captured here... diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 6721d41bb73c9..bd3f3efad82f2 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -4,10 +4,10 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn f(self: Pin<&Self>) -> impl Clone { self } | ---------- ---------- ^^^^ ...and is captured here | | | - | | ...is required to live as long as `'static` by this... + | | ...is required to live as long as `'static` here... | this data with an anonymous lifetime `'_`... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound | LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } | ^^^^ diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index ba56255af5b0c..d96a5f961bdb8 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -10,7 +10,7 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/missing-lifetimes-in-signature.rs:19:5 | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() - | ------ ------------- ...is required to live as long as `'static` by this... + | ------ ------------- ...is required to live as long as `'static` here... | | | this data with an anonymous lifetime `'_`... ... @@ -19,7 +19,7 @@ LL | | *dest = g.get(); LL | | } | |_____^ ...and is captured here | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the `impl Trait` captures data from argument `dest`, you can add an explicit `'_` lifetime bound | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ | ^^^^ diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index 20d3640d4118e..7c649f9c08d64 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -7,7 +7,7 @@ LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to LL | Box::new(items.iter()) | ---------------^^^^--- ...is captured and required live as long as `'static` here | -help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the trait object captures data from argument `items`, you can add an explicit `'_` lifetime bound | LL | fn a(items: &[T]) -> Box + '_> { | ^^^^ From bdfb9b18ab7ba6c4fc27c79dde62d678c25f3b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 1 Jun 2020 17:51:12 -0700 Subject: [PATCH 15/45] Use note for requirement source span --- .../nice_region_error/static_impl_trait.rs | 10 +--- .../ui/async-await/issues/issue-62097.stderr | 6 ++- .../must_outlive_least_region_or_bound.stderr | 50 +++++++++++++------ .../static-return-lifetime-infered.stderr | 22 +++++--- ...types_pin_lifetime_impl_trait-async.stderr | 11 ++-- ..._self_types_pin_lifetime_impl_trait.stderr | 10 ++-- .../missing-lifetimes-in-signature.stderr | 11 ++-- 7 files changed, 77 insertions(+), 43 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 86f310eb71d76..74267a8dec059 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -77,18 +77,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { sup_origin.span(), "...is captured here, requiring it to live as long as `'static`", ); - } else if sup_origin.span() <= return_sp { + } else { err.span_label(sup_origin.span(), "...is captured here..."); - err.span_label( + err.span_note( return_sp, "...and is required to live as long as `'static` here", ); - } else { - err.span_label( - return_sp, - "...is required to live as long as `'static` here...", - ); - err.span_label(sup_origin.span(), "...and is captured here"); } } else { err.span_label( diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index e9f155c6ced31..ff7007dd30b1b 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -6,8 +6,12 @@ LL | pub async fn run_dummy_fn(&self) { | | | this data with an anonymous lifetime `'_`... | ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/issue-62097.rs:13:9 + | LL | foo(|| self.bar()).await; - | --- ...and is required to live as long as `'static` here + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index a9fa0e93fed61..698464b4971a7 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -2,11 +2,15 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:3:35 | LL | fn elided(x: &i32) -> impl Copy { x } - | ---- --------- ^ ...and is captured here - | | | - | | ...is required to live as long as `'static` here... + | ---- ^ ...is captured here... + | | | this data with an anonymous lifetime `'_`... | +note: ...and is required to live as long as `'static` here + --> $DIR/must_outlive_least_region_or_bound.rs:3:23 + | +LL | fn elided(x: &i32) -> impl Copy { x } + | ^^^^^^^^^ help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound | LL | fn elided(x: &i32) -> impl Copy + '_ { x } @@ -16,11 +20,15 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:6:44 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } - | ------- --------- ^ ...and is captured here - | | | - | | ...is required to live as long as `'static` here... + | ------- ^ ...is captured here... + | | | this data with lifetime `'a`... | +note: ...and is required to live as long as `'static` here + --> $DIR/must_outlive_least_region_or_bound.rs:6:32 + | +LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } + | ^^^^^^^^^ help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'a` lifetime bound | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } @@ -30,11 +38,15 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:9:46 | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } - | ---- ------------------- ^ ...and is captured here - | | | - | | ...is required to live as long as `'static` here... + | ---- ^ ...is captured here... + | | | this data with an anonymous lifetime `'_`... | +note: ...and is required to live as long as `'static` here + --> $DIR/must_outlive_least_region_or_bound.rs:9:24 + | +LL | fn elided2(x: &i32) -> impl Copy + 'static { x } + | ^^^^^^^^^^^^^^^^^^^ help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` | LL | fn elided2(x: &i32) -> impl Copy + '_ { x } @@ -48,11 +60,15 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:12:55 | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } - | ------- ------------------- ^ ...and is captured here - | | | - | | ...is required to live as long as `'static` here... + | ------- ^ ...is captured here... + | | | this data with lifetime `'a`... | +note: ...and is required to live as long as `'static` here + --> $DIR/must_outlive_least_region_or_bound.rs:12:33 + | +LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } + | ^^^^^^^^^^^^^^^^^^^ help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } @@ -74,11 +90,13 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:33:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } - | ------- -------------------------------- ^ ...and is captured here - | | | - | | ...is required to live as long as `'static` here... - | this data with lifetime `'a`... + | ------- this data with lifetime `'a`... ^ ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/must_outlive_least_region_or_bound.rs:33:34 | +LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x } diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index 6681eaa909ee0..bcc46785c5918 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -2,14 +2,17 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:7:16 | LL | fn iter_values_anon(&self) -> impl Iterator { - | ----- ----------------------- ...is required to live as long as `'static` here... - | | - | this data with an anonymous lifetime `'_`... + | ----- this data with an anonymous lifetime `'_`... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | - | ...and is captured here + | ...is captured here... | +note: ...and is required to live as long as `'static` here + --> $DIR/static-return-lifetime-infered.rs:6:35 + | +LL | fn iter_values_anon(&self) -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { @@ -19,14 +22,17 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:11:16 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | -------- ----------------------- ...is required to live as long as `'static` here... - | | - | this data with lifetime `'a`... + | -------- this data with lifetime `'a`... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | - | ...and is captured here + | ...is captured here... | +note: ...and is required to live as long as `'static` here + --> $DIR/static-return-lifetime-infered.rs:10:37 + | +LL | fn iter_values<'a>(&'a self) -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 365e38515b12c..2ffbf6e08158e 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -2,10 +2,15 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^ ---------- ---------- ...and is required to live as long as `'static` here - | | | - | | this data with an anonymous lifetime `'_`... + | ^^^^ ---------- this data with an anonymous lifetime `'_`... + | | | ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37 + | +LL | async fn f(self: Pin<&Self>) -> impl Clone { self } + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index bd3f3efad82f2..2da7bcf543d66 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -2,11 +2,15 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44 | LL | fn f(self: Pin<&Self>) -> impl Clone { self } - | ---------- ---------- ^^^^ ...and is captured here - | | | - | | ...is required to live as long as `'static` here... + | ---------- ^^^^ ...is captured here... + | | | this data with an anonymous lifetime `'_`... | +note: ...and is required to live as long as `'static` here + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:31 + | +LL | fn f(self: Pin<&Self>) -> impl Clone { self } + | ^^^^^^^^^^ help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound | LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index d96a5f961bdb8..95d905af05089 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -10,15 +10,18 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/missing-lifetimes-in-signature.rs:19:5 | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() - | ------ ------------- ...is required to live as long as `'static` here... - | | - | this data with an anonymous lifetime `'_`... + | ------ this data with an anonymous lifetime `'_`... ... LL | / move || { LL | | *dest = g.get(); LL | | } - | |_____^ ...and is captured here + | |_____^ ...is captured here... | +note: ...and is required to live as long as `'static` here + --> $DIR/missing-lifetimes-in-signature.rs:15:37 + | +LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + | ^^^^^^^^^^^^^ help: to declare that the `impl Trait` captures data from argument `dest`, you can add an explicit `'_` lifetime bound | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ From 215de3b3c5105982978582861b95b0b449dbff94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 2 Jun 2020 10:47:58 -0700 Subject: [PATCH 16/45] Register new eror code --- src/test/ui/async-await/issues/issue-62097.stderr | 1 + .../ui/impl-trait/must_outlive_least_region_or_bound.stderr | 2 +- src/test/ui/impl-trait/static-return-lifetime-infered.stderr | 1 + src/test/ui/issues/issue-16922.stderr | 1 + .../object-lifetime-default-from-box-error.stderr | 3 ++- src/test/ui/regions/region-object-lifetime-in-coercion.stderr | 3 ++- src/test/ui/regions/regions-close-object-into-object-2.stderr | 1 + src/test/ui/regions/regions-close-object-into-object-4.stderr | 1 + src/test/ui/regions/regions-proc-bound-capture.stderr | 1 + .../arbitrary_self_types_pin_lifetime_impl_trait-async.stderr | 1 + .../self/arbitrary_self_types_pin_lifetime_impl_trait.stderr | 1 + .../lifetimes/missing-lifetimes-in-signature.stderr | 2 +- src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr | 1 + 13 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index ff7007dd30b1b..b3754cce40833 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -15,3 +15,4 @@ LL | foo(|| self.bar()).await; error: aborting due to previous error +For more information about this error, try `rustc --explain E0758`. diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 698464b4971a7..5ab450a85d9e1 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -183,5 +183,5 @@ LL | fn explicit4<'a>(x: &'static i32) -> Box { Box::new(x) error: aborting due to 12 previous errors -Some errors have detailed explanations: E0310, E0621, E0623. +Some errors have detailed explanations: E0310, E0621, E0623, E0758. For more information about an error, try `rustc --explain E0310`. diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index bcc46785c5918..90aada01d9917 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -40,3 +40,4 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0758`. diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 95f46bd7f3eb6..ec80f6569f5ac 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -13,3 +13,4 @@ LL | fn foo(value: &T) -> Box { error: aborting due to previous error +For more information about this error, try `rustc --explain E0758`. diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index e585db262f2d8..ac7502e004c44 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -23,4 +23,5 @@ LL | ss.r = b; error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0621`. +Some errors have detailed explanations: E0621, E0758. +For more information about an error, try `rustc --explain E0621`. diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 8d048d90cb345..fe191e9b69565 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -79,4 +79,5 @@ LL | Box::new(v) error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0495`. +Some errors have detailed explanations: E0495, E0758. +For more information about an error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 5dfe384112b2a..2ea970afcede2 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -17,3 +17,4 @@ LL | fn g<'a, T: 'static>(v: std::boxed::Box<(dyn A + 'static)>) -> Box(v: std::boxed::Box<(dyn A + 'static)>) -> Box Box (isize) + 'static> error: aborting due to previous error +For more information about this error, try `rustc --explain E0758`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 2ffbf6e08158e..69022607bd19e 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -14,3 +14,4 @@ LL | async fn f(self: Pin<&Self>) -> impl Clone { self } error: aborting due to previous error +For more information about this error, try `rustc --explain E0758`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 2da7bcf543d66..c37eb2d136ef1 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -18,3 +18,4 @@ LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } error: aborting due to previous error +For more information about this error, try `rustc --explain E0758`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 95d905af05089..7e8ab1bfe1633 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -125,5 +125,5 @@ LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a error: aborting due to 7 previous errors -Some errors have detailed explanations: E0261, E0309, E0621. +Some errors have detailed explanations: E0261, E0309, E0621, E0758. For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index 7c649f9c08d64..e768d7c8ab99f 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -14,3 +14,4 @@ LL | fn a(items: &[T]) -> Box + '_> { error: aborting due to previous error +For more information about this error, try `rustc --explain E0758`. From 187e1050a2d0ffd822e2ccc0baf8df9679bbde20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 2 Jun 2020 16:05:48 -0700 Subject: [PATCH 17/45] small tweaks --- .../nice_region_error/static_impl_trait.rs | 20 +++++++++++++------ .../ui/async-await/issues/issue-62097.stderr | 6 +----- .../must_outlive_least_region_or_bound.stderr | 10 +++++----- ...ect-lifetime-default-from-box-error.stderr | 2 +- .../region-object-lifetime-in-coercion.stderr | 4 ++-- .../regions-close-object-into-object-2.stderr | 2 +- .../regions-close-object-into-object-4.stderr | 2 +- .../regions/regions-proc-bound-capture.stderr | 2 +- ...types_pin_lifetime_impl_trait-async.stderr | 11 +++------- .../dyn-trait-underscore.stderr | 2 +- 10 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 74267a8dec059..5ad76e3964038 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -79,15 +79,22 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ); } else { err.span_label(sup_origin.span(), "...is captured here..."); - err.span_note( - return_sp, - "...and is required to live as long as `'static` here", - ); + if return_sp < sup_origin.span() { + err.span_note( + return_sp, + "...and is required to live as long as `'static` here", + ); + } else { + err.span_label( + return_sp, + "...and is required to live as long as `'static` here", + ); + } } } else { err.span_label( return_sp, - "...is captured and required live as long as `'static` here", + "...is captured and required to live as long as `'static` here", ); } @@ -104,7 +111,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }; let explicit = format!("you can add an explicit `{}` lifetime bound", lifetime_name); - let explicit_static = format!("explicit `'static` bound to {}", arg); + let explicit_static = + format!("explicit `'static` bound to the lifetime of {}", arg); let captures = format!("captures data from {}", arg); let add_static_bound = "alternatively, add an explicit `'static` bound to this reference"; diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index b3754cce40833..aa443b9d2fc16 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -6,12 +6,8 @@ LL | pub async fn run_dummy_fn(&self) { | | | this data with an anonymous lifetime `'_`... | ...is captured here... - | -note: ...and is required to live as long as `'static` here - --> $DIR/issue-62097.rs:13:9 - | LL | foo(|| self.bar()).await; - | ^^^ + | --- ...and is required to live as long as `'static` here error: aborting due to previous error diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 5ab450a85d9e1..baed43783a13c 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -47,7 +47,7 @@ note: ...and is required to live as long as `'static` here | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^^^^^^^^ -help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` +help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x` | LL | fn elided2(x: &i32) -> impl Copy + '_ { x } | ^^ @@ -69,7 +69,7 @@ note: ...and is required to live as long as `'static` here | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^^^^^^^^ -help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` +help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x` | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^ @@ -97,7 +97,7 @@ note: ...and is required to live as long as `'static` here | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` +help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x` | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x } | ^^ @@ -157,7 +157,7 @@ LL | fn elided4(x: &i32) -> Box { Box::new(x) } | | | this data with an anonymous lifetime `'_`... | -help: consider changing the trait object's explicit `'static` bound to argument `x` +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` | LL | fn elided4(x: &i32) -> Box { Box::new(x) } | ^^ @@ -172,7 +172,7 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } | ------- this data with lifetime `'a`... ^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to argument `x` +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^ diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index ac7502e004c44..d461001adead9 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -5,7 +5,7 @@ LL | fn load(ss: &mut SomeStruct) -> Box { | --------------- this data with an anonymous lifetime `'_`... ... LL | ss.r - | ^^^^ ...is captured and required live as long as `'static` here + | ^^^^ ...is captured and required to live as long as `'static` here | help: to declare that the trait object captures data from argument `ss`, you can add an explicit `'_` lifetime bound | diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index fe191e9b69565..c684373c67e9d 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -6,7 +6,7 @@ LL | fn a(v: &[u8]) -> Box { LL | let x: Box = Box::new(v); | ^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to argument `v` +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` | LL | fn a(v: &[u8]) -> Box { | ^^ @@ -23,7 +23,7 @@ LL | fn b(v: &[u8]) -> Box { LL | Box::new(v) | ^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to argument `v` +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` | LL | fn b(v: &[u8]) -> Box { | ^^ diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 2ea970afcede2..c4ba395179831 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -6,7 +6,7 @@ LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { LL | box B(&*v) as Box | ^^^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to argument `v` +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { | ^^ diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index 493b7a1df9920..e45930bd95710 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -6,7 +6,7 @@ LL | fn i<'a, T, U>(v: Box+'a>) -> Box { LL | box B(&*v) as Box | ^^^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to argument `v` +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { | ^^ diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index c10b9850a4e99..69c7256364d70 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -7,7 +7,7 @@ LL | // This is illegal, because the region bound on `proc` is 'static. LL | Box::new(move || { *x }) | ^^^^^^^^^^^^^^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to argument `x` +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` | LL | fn static_proc(x: &isize) -> Box (isize) + '_> { | ^^ diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 69022607bd19e..9b04069136be2 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -2,15 +2,10 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^ ---------- this data with an anonymous lifetime `'_`... - | | + | ^^^^ ---------- ---------- ...and is required to live as long as `'static` here + | | | + | | this data with an anonymous lifetime `'_`... | ...is captured here... - | -note: ...and is required to live as long as `'static` here - --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37 - | -LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index e768d7c8ab99f..fc4c801949512 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -5,7 +5,7 @@ LL | fn a(items: &[T]) -> Box> { | ---- this data with an anonymous lifetime `'_`... LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | Box::new(items.iter()) - | ---------------^^^^--- ...is captured and required live as long as `'static` here + | ---------------^^^^--- ...is captured and required to live as long as `'static` here | help: to declare that the trait object captures data from argument `items`, you can add an explicit `'_` lifetime bound | From 6145918c83d10e9679805b8feff0286ce9e58afc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 3 Jun 2020 11:34:04 -0700 Subject: [PATCH 18/45] Change E0758 to E0759 to avoid conflict with #72912 --- src/librustc_error_codes/error_codes.rs | 1 + src/librustc_error_codes/error_codes/E0759.md | 67 +++++++++++++++++++ .../nice_region_error/static_impl_trait.rs | 2 +- .../ui/async-await/issues/issue-62097.stderr | 4 +- .../must_outlive_least_region_or_bound.stderr | 20 +++--- .../static-return-lifetime-infered.stderr | 6 +- src/test/ui/issues/issue-16922.stderr | 4 +- ...ect-lifetime-default-from-box-error.stderr | 4 +- .../region-object-lifetime-in-coercion.stderr | 8 +-- .../regions-close-object-into-object-2.stderr | 4 +- .../regions-close-object-into-object-4.stderr | 4 +- .../regions/regions-proc-bound-capture.stderr | 4 +- ...types_pin_lifetime_impl_trait-async.stderr | 4 +- ..._self_types_pin_lifetime_impl_trait.stderr | 4 +- .../missing-lifetimes-in-signature.stderr | 4 +- .../dyn-trait-underscore.stderr | 4 +- 16 files changed, 106 insertions(+), 38 deletions(-) create mode 100644 src/librustc_error_codes/error_codes/E0759.md diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 760b4d7ba00a3..2e3ba13f37911 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -438,6 +438,7 @@ E0752: include_str!("./error_codes/E0752.md"), E0753: include_str!("./error_codes/E0753.md"), E0754: include_str!("./error_codes/E0754.md"), E0758: include_str!("./error_codes/E0758.md"), +E0759: include_str!("./error_codes/E0759.md"), E0760: include_str!("./error_codes/E0760.md"), ; // E0006, // merged with E0005 diff --git a/src/librustc_error_codes/error_codes/E0759.md b/src/librustc_error_codes/error_codes/E0759.md new file mode 100644 index 0000000000000..a74759bdf634b --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0759.md @@ -0,0 +1,67 @@ +A `'static` requirement in a return type involving a trait is not fulfilled. + +Erroneous code examples: + +```compile_fail,E0759 +use std::fmt::Debug; + +fn foo(x: &i32) -> impl Debug { + x +} +``` + +```compile_fail,E0759 +# use std::fmt::Debug; +fn bar(x: &i32) -> Box { + Box::new(x) +} +``` + +These examples have the same semantics as the following: + +```compile_fail,E0759 +# use std::fmt::Debug; +fn foo(x: &i32) -> impl Debug + 'static { + x +} +``` + +```compile_fail,E0759 +# use std::fmt::Debug; +fn bar(x: &i32) -> Box { + Box::new(x) +} +``` + +Both [`dyn Trait`] and [`impl Trait`] in return types have a an implicit +`'static` requirement, meaning that the value implementing them that is being +returned has to be either a `'static` borrow or an owned value. + +In order to change the requirement from `'static` to be a lifetime derived from +its arguments, you can add an explicit bound, either to an anonymous lifetime +`'_` or some appropriate named lifetime. + +``` +# use std::fmt::Debug; +fn foo(x: &i32) -> impl Debug + '_ { + x +} +fn bar(x: &i32) -> Box { + Box::new(x) +} +``` + +These are equivalent to the following explicit lifetime annotations: + +``` +# use std::fmt::Debug; +fn foo<'a>(x: &'a i32) -> impl Debug + 'a { + x +} +fn bar<'a>(x: &'a i32) -> Box { + Box::new(x) +} +``` + +[`dyn Trait`]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types +[`impl Trait`]: https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 5ad76e3964038..853a414290704 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -40,7 +40,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let mut err = struct_span_err!( self.tcx().sess, sp, - E0758, + E0759, "cannot infer an appropriate lifetime" ); err.span_label( diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index aa443b9d2fc16..0f58b158904db 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/issue-62097.rs:12:31 | LL | pub async fn run_dummy_fn(&self) { @@ -11,4 +11,4 @@ LL | foo(|| self.bar()).await; error: aborting due to previous error -For more information about this error, try `rustc --explain E0758`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index baed43783a13c..e1fa4f02b6fcf 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:3:35 | LL | fn elided(x: &i32) -> impl Copy { x } @@ -16,7 +16,7 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:6:44 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } @@ -34,7 +34,7 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:9:46 | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } @@ -56,7 +56,7 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:12:55 | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } @@ -86,7 +86,7 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | | | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:33:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } @@ -123,7 +123,7 @@ LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | | | help: consider adding an explicit lifetime bound...: `T: 'static +` -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:18:50 | LL | fn elided3(x: &i32) -> Box { Box::new(x) } @@ -136,7 +136,7 @@ help: to declare that the trait object captures data from argument `x`, you can LL | fn elided3(x: &i32) -> Box { Box::new(x) } | ^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:21:59 | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } @@ -149,7 +149,7 @@ help: to declare that the trait object captures data from argument `x`, you can LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:24:60 | LL | fn elided4(x: &i32) -> Box { Box::new(x) } @@ -166,7 +166,7 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn elided4(x: &'static i32) -> Box { Box::new(x) } | ^^^^^^^^^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:27:69 | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } @@ -183,5 +183,5 @@ LL | fn explicit4<'a>(x: &'static i32) -> Box { Box::new(x) error: aborting due to 12 previous errors -Some errors have detailed explanations: E0310, E0621, E0623, E0758. +Some errors have detailed explanations: E0310, E0621, E0623, E0759. For more information about an error, try `rustc --explain E0310`. diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index 90aada01d9917..df0db6e4fc6df 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:7:16 | LL | fn iter_values_anon(&self) -> impl Iterator { @@ -18,7 +18,7 @@ help: to declare that the `impl Trait` captures data from argument `self`, you c LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:11:16 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { @@ -40,4 +40,4 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0758`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index ec80f6569f5ac..919594fc9af4b 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/issue-16922.rs:4:14 | LL | fn foo(value: &T) -> Box { @@ -13,4 +13,4 @@ LL | fn foo(value: &T) -> Box { error: aborting due to previous error -For more information about this error, try `rustc --explain E0758`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index d461001adead9..1b1e0d9610724 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/object-lifetime-default-from-box-error.rs:18:5 | LL | fn load(ss: &mut SomeStruct) -> Box { @@ -23,5 +23,5 @@ LL | ss.r = b; error: aborting due to 2 previous errors -Some errors have detailed explanations: E0621, E0758. +Some errors have detailed explanations: E0621, E0759. For more information about an error, try `rustc --explain E0621`. diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index c684373c67e9d..7f5a3a47976c7 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:8:46 | LL | fn a(v: &[u8]) -> Box { @@ -15,7 +15,7 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn a(v: &'static [u8]) -> Box { | ^^^^^^^^^^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:13:14 | LL | fn b(v: &[u8]) -> Box { @@ -32,7 +32,7 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn b(v: &'static [u8]) -> Box { | ^^^^^^^^^^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:19:14 | LL | fn c(v: &[u8]) -> Box { @@ -79,5 +79,5 @@ LL | Box::new(v) error: aborting due to 4 previous errors -Some errors have detailed explanations: E0495, E0758. +Some errors have detailed explanations: E0495, E0759. For more information about an error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index c4ba395179831..114e4052aae09 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/regions-close-object-into-object-2.rs:10:11 | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { @@ -17,4 +17,4 @@ LL | fn g<'a, T: 'static>(v: std::boxed::Box<(dyn A + 'static)>) -> Box $DIR/regions-close-object-into-object-4.rs:10:11 | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { @@ -17,4 +17,4 @@ LL | fn i<'a, T, U>(v: std::boxed::Box<(dyn A + 'static)>) -> Box $DIR/regions-proc-bound-capture.rs:9:14 | LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { @@ -18,4 +18,4 @@ LL | fn static_proc(x: &'static isize) -> Box (isize) + 'static> error: aborting due to previous error -For more information about this error, try `rustc --explain E0758`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 9b04069136be2..88bd990b1e81b 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } @@ -9,4 +9,4 @@ LL | async fn f(self: Pin<&Self>) -> impl Clone { self } error: aborting due to previous error -For more information about this error, try `rustc --explain E0758`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index c37eb2d136ef1..2e10ab3d3f9b8 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44 | LL | fn f(self: Pin<&Self>) -> impl Clone { self } @@ -18,4 +18,4 @@ LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } error: aborting due to previous error -For more information about this error, try `rustc --explain E0758`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 7e8ab1bfe1633..9ab060328537b 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -6,7 +6,7 @@ LL | fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ | | | help: consider introducing lifetime `'a` here: `'a,` -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/missing-lifetimes-in-signature.rs:19:5 | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() @@ -125,5 +125,5 @@ LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a error: aborting due to 7 previous errors -Some errors have detailed explanations: E0261, E0309, E0621, E0758. +Some errors have detailed explanations: E0261, E0309, E0621, E0759. For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index fc4c801949512..dda5de431d309 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/dyn-trait-underscore.rs:8:20 | LL | fn a(items: &[T]) -> Box> { @@ -14,4 +14,4 @@ LL | fn a(items: &[T]) -> Box + '_> { error: aborting due to previous error -For more information about this error, try `rustc --explain E0758`. +For more information about this error, try `rustc --explain E0759`. From 88ea7e5234bff0c4fcf5859aa6d5dd8d0608b853 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 1 Jun 2020 18:58:18 +0100 Subject: [PATCH 19/45] Use min_specialization in the remaining rustc crates --- src/librustc_arena/lib.rs | 29 ++-- src/librustc_ast_lowering/lib.rs | 2 +- src/librustc_hir/arena.rs | 70 ++++----- .../infer/canonical/query_response.rs | 2 +- src/librustc_macros/src/query.rs | 4 +- src/librustc_metadata/lib.rs | 2 +- src/librustc_metadata/rmeta/decoder.rs | 17 ++- src/librustc_metadata/rmeta/encoder.rs | 35 +++-- src/librustc_middle/arena.rs | 76 +++++++--- src/librustc_middle/dep_graph/dep_node.rs | 27 +++- src/librustc_middle/lib.rs | 2 +- src/librustc_middle/mir/mod.rs | 37 ++++- src/librustc_middle/ty/codec.rs | 142 +++++++++++------- src/librustc_middle/ty/query/on_disk_cache.rs | 60 ++------ .../ty/query/profiling_support.rs | 41 +++-- src/librustc_middle/ty/query/values.rs | 20 ++- src/librustc_middle/ty/sty.rs | 2 - .../dep_graph/dep_node.rs | 9 +- src/librustc_query_system/lib.rs | 2 +- src/librustc_serialize/lib.rs | 2 +- src/librustc_serialize/serialize.rs | 36 ++--- src/librustc_trait_selection/infer.rs | 4 +- 22 files changed, 373 insertions(+), 248 deletions(-) diff --git a/src/librustc_arena/lib.rs b/src/librustc_arena/lib.rs index bbe80c26dcbf9..4ea5ec3c1de82 100644 --- a/src/librustc_arena/lib.rs +++ b/src/librustc_arena/lib.rs @@ -610,7 +610,7 @@ macro_rules! which_arena_for_type { #[macro_export] macro_rules! declare_arena { - ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => { + ([], [$($a:tt $name:ident: $ty:ty, $gen_ty:ty;)*], $tcx:lifetime) => { #[derive(Default)] pub struct Arena<$tcx> { pub dropless: $crate::DroplessArena, @@ -619,17 +619,17 @@ macro_rules! declare_arena { } #[marker] - pub trait ArenaAllocatable {} + pub trait ArenaAllocatable<'tcx> {} - impl ArenaAllocatable for T {} + impl<'tcx, T: Copy> ArenaAllocatable<'tcx> for T {} - unsafe trait ArenaField<'tcx>: Sized { + unsafe trait ArenaField<'tcx>: Sized + ArenaAllocatable<'tcx> { /// Returns a specific arena to allocate from. /// If `None` is returned, the `DropArena` will be used. fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena>; } - unsafe impl<'tcx, T> ArenaField<'tcx> for T { + unsafe impl<'tcx, T: ArenaAllocatable<'tcx>> ArenaField<'tcx> for T { #[inline] default fn arena<'a>(_: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena> { panic!() @@ -638,18 +638,27 @@ macro_rules! declare_arena { $( #[allow(unused_lifetimes)] - impl<$tcx> ArenaAllocatable for $ty {} - unsafe impl<$tcx> ArenaField<$tcx> for $ty { + impl<$tcx> ArenaAllocatable<$tcx> for $ty {} + unsafe impl<$tcx, '_x, '_y, '_z, '_w> ArenaField<$tcx> for $gen_ty where Self: ArenaAllocatable<$tcx> { #[inline] fn arena<'a>(_arena: &'a Arena<$tcx>) -> Option<&'a $crate::TypedArena> { - $crate::which_arena_for_type!($a[&_arena.$name]) + // SAFETY: We only implement `ArenaAllocatable<$tcx>` for + // `$ty`, so `$ty` and Self are the same type + unsafe { + ::std::mem::transmute::< + Option<&'a $crate::TypedArena<$ty>>, + Option<&'a $crate::TypedArena>, + >( + $crate::which_arena_for_type!($a[&_arena.$name]) + ) + } } } )* impl<'tcx> Arena<'tcx> { #[inline] - pub fn alloc(&self, value: T) -> &mut T { + pub fn alloc>(&self, value: T) -> &mut T { if !::std::mem::needs_drop::() { return self.dropless.alloc(value); } @@ -667,7 +676,7 @@ macro_rules! declare_arena { self.dropless.alloc_slice(value) } - pub fn alloc_from_iter<'a, T: ArenaAllocatable>( + pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx>>( &'a self, iter: impl ::std::iter::IntoIterator, ) -> &'a mut [T] { diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 1f8c68f75e943..7b1535351262a 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -33,7 +33,7 @@ #![feature(array_value_iter)] #![feature(crate_visibility_modifier)] #![feature(marker_trait_attr)] -#![feature(specialization)] // FIXME: min_specialization does not work +#![feature(min_specialization)] #![feature(or_patterns)] #![recursion_limit = "256"] diff --git a/src/librustc_hir/arena.rs b/src/librustc_hir/arena.rs index 6ba396666070a..f439db715310c 100644 --- a/src/librustc_hir/arena.rs +++ b/src/librustc_hir/arena.rs @@ -12,41 +12,41 @@ macro_rules! arena_types { ($macro:path, $args:tt, $tcx:lifetime) => ( $macro!($args, [ // HIR types - [few] hir_krate: rustc_hir::Crate<$tcx>, - [] arm: rustc_hir::Arm<$tcx>, - [] asm_operand: rustc_hir::InlineAsmOperand<$tcx>, - [] asm_template: rustc_ast::ast::InlineAsmTemplatePiece, - [] attribute: rustc_ast::ast::Attribute, - [] block: rustc_hir::Block<$tcx>, - [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>, - [few] global_asm: rustc_hir::GlobalAsm, - [] generic_arg: rustc_hir::GenericArg<$tcx>, - [] generic_args: rustc_hir::GenericArgs<$tcx>, - [] generic_bound: rustc_hir::GenericBound<$tcx>, - [] generic_param: rustc_hir::GenericParam<$tcx>, - [] expr: rustc_hir::Expr<$tcx>, - [] field: rustc_hir::Field<$tcx>, - [] field_pat: rustc_hir::FieldPat<$tcx>, - [] fn_decl: rustc_hir::FnDecl<$tcx>, - [] foreign_item: rustc_hir::ForeignItem<$tcx>, - [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>, - [few] inline_asm: rustc_hir::InlineAsm<$tcx>, - [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>, - [] local: rustc_hir::Local<$tcx>, - [few] macro_def: rustc_hir::MacroDef<$tcx>, - [] param: rustc_hir::Param<$tcx>, - [] pat: rustc_hir::Pat<$tcx>, - [] path: rustc_hir::Path<$tcx>, - [] path_segment: rustc_hir::PathSegment<$tcx>, - [] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>, - [] qpath: rustc_hir::QPath<$tcx>, - [] stmt: rustc_hir::Stmt<$tcx>, - [] struct_field: rustc_hir::StructField<$tcx>, - [] trait_item_ref: rustc_hir::TraitItemRef, - [] ty: rustc_hir::Ty<$tcx>, - [] type_binding: rustc_hir::TypeBinding<$tcx>, - [] variant: rustc_hir::Variant<$tcx>, - [] where_predicate: rustc_hir::WherePredicate<$tcx>, + [few] hir_krate: rustc_hir::Crate<$tcx>, rustc_hir::Crate<'_x>; + [] arm: rustc_hir::Arm<$tcx>, rustc_hir::Arm<'_x>; + [] asm_operand: rustc_hir::InlineAsmOperand<$tcx>, rustc_hir::InlineAsmOperand<'_x>; + [] asm_template: rustc_ast::ast::InlineAsmTemplatePiece, rustc_ast::ast::InlineAsmTemplatePiece; + [] attribute: rustc_ast::ast::Attribute, rustc_ast::ast::Attribute; + [] block: rustc_hir::Block<$tcx>, rustc_hir::Block<'_x>; + [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>, rustc_hir::BareFnTy<'_x>; + [few] global_asm: rustc_hir::GlobalAsm, rustc_hir::GlobalAsm; + [] generic_arg: rustc_hir::GenericArg<$tcx>, rustc_hir::GenericArg<'_x>; + [] generic_args: rustc_hir::GenericArgs<$tcx>, rustc_hir::GenericArgs<'_x>; + [] generic_bound: rustc_hir::GenericBound<$tcx>, rustc_hir::GenericBound<'_x>; + [] generic_param: rustc_hir::GenericParam<$tcx>, rustc_hir::GenericParam<'_x>; + [] expr: rustc_hir::Expr<$tcx>, rustc_hir::Expr<'_x>; + [] field: rustc_hir::Field<$tcx>, rustc_hir::Field<'_x>; + [] field_pat: rustc_hir::FieldPat<$tcx>, rustc_hir::FieldPat<'_x>; + [] fn_decl: rustc_hir::FnDecl<$tcx>, rustc_hir::FnDecl<'_x>; + [] foreign_item: rustc_hir::ForeignItem<$tcx>, rustc_hir::ForeignItem<'_x>; + [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>, rustc_hir::ImplItemRef<'_x>; + [few] inline_asm: rustc_hir::InlineAsm<$tcx>, rustc_hir::InlineAsm<'_x>; + [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>, rustc_hir::LlvmInlineAsm<'_x>; + [] local: rustc_hir::Local<$tcx>, rustc_hir::Local<'_x>; + [few] macro_def: rustc_hir::MacroDef<$tcx>, rustc_hir::MacroDef<'_x>; + [] param: rustc_hir::Param<$tcx>, rustc_hir::Param<'_x>; + [] pat: rustc_hir::Pat<$tcx>, rustc_hir::Pat<'_x>; + [] path: rustc_hir::Path<$tcx>, rustc_hir::Path<'_x>; + [] path_segment: rustc_hir::PathSegment<$tcx>, rustc_hir::PathSegment<'_x>; + [] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>, rustc_hir::PolyTraitRef<'_x>; + [] qpath: rustc_hir::QPath<$tcx>, rustc_hir::QPath<'_x>; + [] stmt: rustc_hir::Stmt<$tcx>, rustc_hir::Stmt<'_x>; + [] struct_field: rustc_hir::StructField<$tcx>, rustc_hir::StructField<'_x>; + [] trait_item_ref: rustc_hir::TraitItemRef, rustc_hir::TraitItemRef; + [] ty: rustc_hir::Ty<$tcx>, rustc_hir::Ty<'_x>; + [] type_binding: rustc_hir::TypeBinding<$tcx>, rustc_hir::TypeBinding<'_x>; + [] variant: rustc_hir::Variant<$tcx>, rustc_hir::Variant<'_x>; + [] where_predicate: rustc_hir::WherePredicate<$tcx>, rustc_hir::WherePredicate<'_x>; ], $tcx); ) } diff --git a/src/librustc_infer/infer/canonical/query_response.rs b/src/librustc_infer/infer/canonical/query_response.rs index ab2393918c354..8af526e3ad31b 100644 --- a/src/librustc_infer/infer/canonical/query_response.rs +++ b/src/librustc_infer/infer/canonical/query_response.rs @@ -56,7 +56,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { ) -> Fallible> where T: Debug + TypeFoldable<'tcx>, - Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable, + Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>, { let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?; let canonical_result = self.canonicalize_response(&query_response); diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs index 41a49a38a19cf..c17d5311e8fe6 100644 --- a/src/librustc_macros/src/query.rs +++ b/src/librustc_macros/src/query.rs @@ -433,7 +433,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { try_load_from_on_disk_cache_stream.extend(quote! { ::rustc_middle::dep_graph::DepKind::#name => { - if <#arg as DepNodeParams>>::CAN_RECONSTRUCT_QUERY_KEY { + if <#arg as DepNodeParams>>::can_reconstruct_query_key() { debug_assert!($tcx.dep_graph .node_color($dep_node) .map(|c| c.is_green()) @@ -490,7 +490,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { // Add a match arm to force the query given the dep node dep_node_force_stream.extend(quote! { ::rustc_middle::dep_graph::DepKind::#name => { - if <#arg as DepNodeParams>>::CAN_RECONSTRUCT_QUERY_KEY { + if <#arg as DepNodeParams>>::can_reconstruct_query_key() { if let Some(key) = <#arg as DepNodeParams>>::recover($tcx, $dep_node) { force_query::, _>( $tcx, diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 2a2169880a54e..76e39a476c6d8 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -7,7 +7,7 @@ #![feature(nll)] #![feature(or_patterns)] #![feature(proc_macro_internals)] -#![feature(specialization)] // FIXME: min_specialization ICEs +#![feature(min_specialization)] #![feature(stmt_expr_attributes)] #![recursion_limit = "256"] diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index f5a9dceb78295..fdb5daa985529 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -30,7 +30,7 @@ use rustc_middle::mir::{self, interpret, Body, Promoted}; use rustc_middle::ty::codec::TyDecoder; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::util::common::record_time; -use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder}; +use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder, UseSpecializedDecodable}; use rustc_session::Session; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{sym, Ident, Symbol}; @@ -218,7 +218,7 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) { } } -impl<'a, 'tcx, T: Decodable> Lazy { +impl<'a, 'tcx, T: Decodable> Lazy { fn decode>(self, metadata: M) -> T { let mut dcx = metadata.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); @@ -226,7 +226,7 @@ impl<'a, 'tcx, T: Decodable> Lazy { } } -impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> { +impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T], usize> { fn decode>( self, metadata: M, @@ -321,20 +321,20 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> { } } -impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { +impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { self.read_lazy_with_meta(()) } } -impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { +impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { let len = self.read_usize()?; if len == 0 { Ok(Lazy::empty()) } else { self.read_lazy_with_meta(len) } } } -impl<'a, 'tcx, I: Idx, T> SpecializedDecoder>> for DecodeContext<'a, 'tcx> +impl<'a, 'tcx, I: Idx, T> SpecializedDecoder, usize>> for DecodeContext<'a, 'tcx> where Option: FixedSizeEncoding, { @@ -515,8 +515,9 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { } } -impl<'a, 'tcx, T: Decodable> SpecializedDecoder> - for DecodeContext<'a, 'tcx> +impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> +where + mir::ClearCrossCrate: UseSpecializedDecodable, { #[inline] fn specialized_decode(&mut self) -> Result, Self::Error> { diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 64ccd46a744f5..1258e02bcd4bc 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -27,7 +27,7 @@ use rustc_middle::mir::{self, interpret}; use rustc_middle::traits::specialization_graph; use rustc_middle::ty::codec::{self as ty_codec, TyEncoder}; use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; -use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder}; +use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder, UseSpecializedEncodable}; use rustc_session::config::CrateType; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -93,13 +93,13 @@ impl<'tcx> Encoder for EncodeContext<'tcx> { } } -impl<'tcx, T> SpecializedEncoder> for EncodeContext<'tcx> { +impl<'tcx, T> SpecializedEncoder> for EncodeContext<'tcx> { fn specialized_encode(&mut self, lazy: &Lazy) -> Result<(), Self::Error> { self.emit_lazy_distance(*lazy) } } -impl<'tcx, T> SpecializedEncoder> for EncodeContext<'tcx> { +impl<'tcx, T> SpecializedEncoder> for EncodeContext<'tcx> { fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> { self.emit_usize(lazy.meta)?; if lazy.meta == 0 { @@ -109,7 +109,7 @@ impl<'tcx, T> SpecializedEncoder> for EncodeContext<'tcx> { } } -impl<'tcx, I: Idx, T> SpecializedEncoder>> for EncodeContext<'tcx> +impl<'tcx, I: Idx, T> SpecializedEncoder, usize>> for EncodeContext<'tcx> where Option: FixedSizeEncoding, { @@ -228,8 +228,13 @@ impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { } } -impl<'tcx> SpecializedEncoder> for EncodeContext<'tcx> { - fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> { +impl<'a, 'b, 'tcx> SpecializedEncoder<&'a ty::TyS<'b>> for EncodeContext<'tcx> +where + &'a ty::TyS<'b>: UseSpecializedEncodable, +{ + fn specialized_encode(&mut self, ty: &&'a ty::TyS<'b>) -> Result<(), Self::Error> { + debug_assert!(self.tcx.lift(ty).is_some()); + let ty = unsafe { std::mem::transmute::<&&'a ty::TyS<'b>, &&'tcx ty::TyS<'tcx>>(ty) }; ty_codec::encode_with_shorthand(self, ty, |ecx| &mut ecx.type_shorthands) } } @@ -251,12 +256,19 @@ impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { } } -impl<'tcx> SpecializedEncoder<&'tcx [(ty::Predicate<'tcx>, Span)]> for EncodeContext<'tcx> { +impl<'a, 'b, 'tcx> SpecializedEncoder<&'a [(ty::Predicate<'b>, Span)]> for EncodeContext<'tcx> { fn specialized_encode( &mut self, - predicates: &&'tcx [(ty::Predicate<'tcx>, Span)], + predicates: &&'a [(ty::Predicate<'b>, Span)], ) -> Result<(), Self::Error> { - ty_codec::encode_spanned_predicates(self, predicates, |ecx| &mut ecx.predicate_shorthands) + debug_assert!(self.tcx.lift(*predicates).is_some()); + let predicates = unsafe { + std::mem::transmute::< + &&'a [(ty::Predicate<'b>, Span)], + &&'tcx [(ty::Predicate<'tcx>, Span)], + >(predicates) + }; + ty_codec::encode_spanned_predicates(self, &predicates, |ecx| &mut ecx.predicate_shorthands) } } @@ -266,7 +278,10 @@ impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { } } -impl<'tcx, T: Encodable> SpecializedEncoder> for EncodeContext<'tcx> { +impl<'tcx, T> SpecializedEncoder> for EncodeContext<'tcx> +where + mir::ClearCrossCrate: UseSpecializedEncodable, +{ fn specialized_encode(&mut self, _: &mir::ClearCrossCrate) -> Result<(), Self::Error> { Ok(()) } diff --git a/src/librustc_middle/arena.rs b/src/librustc_middle/arena.rs index 75228350c6c45..f861d63aba0f3 100644 --- a/src/librustc_middle/arena.rs +++ b/src/librustc_middle/arena.rs @@ -11,79 +11,109 @@ macro_rules! arena_types { ($macro:path, $args:tt, $tcx:lifetime) => ( $macro!($args, [ - [] layouts: rustc_target::abi::Layout, + [] layouts: rustc_target::abi::Layout, rustc_target::abi::Layout; // AdtDef are interned and compared by address - [] adt_def: rustc_middle::ty::AdtDef, - [decode] tables: rustc_middle::ty::TypeckTables<$tcx>, - [] const_allocs: rustc_middle::mir::interpret::Allocation, + [] adt_def: rustc_middle::ty::AdtDef, rustc_middle::ty::AdtDef; + [decode] tables: rustc_middle::ty::TypeckTables<$tcx>, rustc_middle::ty::TypeckTables<'_x>; + [] const_allocs: rustc_middle::mir::interpret::Allocation, rustc_middle::mir::interpret::Allocation; // Required for the incremental on-disk cache - [few, decode] mir_keys: rustc_hir::def_id::DefIdSet, - [] region_scope_tree: rustc_middle::middle::region::ScopeTree, + [few, decode] mir_keys: rustc_hir::def_id::DefIdSet, rustc_hir::def_id::DefIdSet; + [] region_scope_tree: rustc_middle::middle::region::ScopeTree, rustc_middle::middle::region::ScopeTree; [] dropck_outlives: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::traits::query::DropckOutlivesResult<'tcx> > >, + rustc_middle::infer::canonical::Canonical<'_x, + rustc_middle::infer::canonical::QueryResponse<'_y, + rustc_middle::traits::query::DropckOutlivesResult<'_z> + > + >; [] normalize_projection_ty: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::traits::query::NormalizationResult<'tcx> > >, + rustc_middle::infer::canonical::Canonical<'_x, + rustc_middle::infer::canonical::QueryResponse<'_y, + rustc_middle::traits::query::NormalizationResult<'_z> + > + >; [] implied_outlives_bounds: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, Vec> > >, + rustc_middle::infer::canonical::Canonical<'_x, + rustc_middle::infer::canonical::QueryResponse<'_y, + Vec> + > + >; [] type_op_subtype: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, ()> >, + rustc_middle::infer::canonical::Canonical<'_x, + rustc_middle::infer::canonical::QueryResponse<'_y, ()> + >; [] type_op_normalize_poly_fn_sig: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::PolyFnSig<'tcx>> >, + rustc_middle::infer::canonical::Canonical<'_x, + rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::PolyFnSig<'_z>> + >; [] type_op_normalize_fn_sig: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::FnSig<'tcx>> >, + rustc_middle::infer::canonical::Canonical<'_x, + rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::FnSig<'_z>> + >; [] type_op_normalize_predicate: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Predicate<'tcx>> >, + rustc_middle::infer::canonical::Canonical<'_x, + rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::Predicate<'_z>> + >; [] type_op_normalize_ty: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Ty<'tcx>> >, - [few] all_traits: Vec, - [few] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels, - [few] foreign_module: rustc_middle::middle::cstore::ForeignModule, - [few] foreign_modules: Vec, - [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap, - [] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation, - [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<$tcx>, - [] attribute: rustc_ast::ast::Attribute, - [] name_set: rustc_data_structures::fx::FxHashSet, - [] hir_id_set: rustc_hir::HirIdSet, + rustc_middle::infer::canonical::Canonical<'_x, + rustc_middle::infer::canonical::QueryResponse<'_y, &'_z rustc_middle::ty::TyS<'_w>> + >; + [few] all_traits: Vec, Vec; + [few] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels, rustc_middle::middle::privacy::AccessLevels; + [few] foreign_module: rustc_middle::middle::cstore::ForeignModule, rustc_middle::middle::cstore::ForeignModule; + [few] foreign_modules: Vec, Vec; + [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap, rustc_data_structures::fx::FxIndexMap; + [] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation, rustc_middle::traits::ObjectSafetyViolation; + [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<$tcx>, rustc_middle::mir::mono::CodegenUnit<'_x>; + [] attribute: rustc_ast::ast::Attribute, rustc_ast::ast::Attribute; + [] name_set: rustc_data_structures::fx::FxHashSet, rustc_data_structures::fx::FxHashSet; + [] hir_id_set: rustc_hir::HirIdSet, rustc_hir::HirIdSet; // Interned types - [] tys: rustc_middle::ty::TyS<$tcx>, + [] tys: rustc_middle::ty::TyS<$tcx>, rustc_middle::ty::TyS<'_x>; // HIR query types - [few] indexed_hir: rustc_middle::hir::map::IndexedHir<$tcx>, - [few] hir_definitions: rustc_hir::definitions::Definitions, - [] hir_owner: rustc_middle::hir::Owner<$tcx>, - [] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>, + [few] indexed_hir: rustc_middle::hir::map::IndexedHir<$tcx>, rustc_middle::hir::map::IndexedHir<'_x>; + [few] hir_definitions: rustc_hir::definitions::Definitions, rustc_hir::definitions::Definitions; + [] hir_owner: rustc_middle::hir::Owner<$tcx>, rustc_middle::hir::Owner<'_x>; + [] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>, rustc_middle::hir::OwnerNodes<'_x>; // Note that this deliberately duplicates items in the `rustc_hir::arena`, // since we need to allocate this type on both the `rustc_hir` arena // (during lowering) and the `librustc_middle` arena (for decoding MIR) - [decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece, + [decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece, rustc_ast::ast::InlineAsmTemplatePiece; // This is used to decode the &'tcx [Span] for InlineAsm's line_spans. - [decode] span: rustc_span::Span, + [decode] span: rustc_span::Span, rustc_span::Span; ], $tcx); ) } diff --git a/src/librustc_middle/dep_graph/dep_node.rs b/src/librustc_middle/dep_graph/dep_node.rs index 2c0524fa99102..b14f17dee6060 100644 --- a/src/librustc_middle/dep_graph/dep_node.rs +++ b/src/librustc_middle/dep_graph/dep_node.rs @@ -128,7 +128,7 @@ macro_rules! define_dep_nodes { // tuple args $({ return <$tuple_arg_ty as DepNodeParams>> - ::CAN_RECONSTRUCT_QUERY_KEY; + ::can_reconstruct_query_key(); })* true @@ -304,7 +304,10 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> ]); impl<'tcx> DepNodeParams> for DefId { - const CAN_RECONSTRUCT_QUERY_KEY: bool = true; + #[inline] + fn can_reconstruct_query_key() -> bool { + true + } fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { tcx.def_path_hash(*self).0 @@ -320,7 +323,10 @@ impl<'tcx> DepNodeParams> for DefId { } impl<'tcx> DepNodeParams> for LocalDefId { - const CAN_RECONSTRUCT_QUERY_KEY: bool = true; + #[inline] + fn can_reconstruct_query_key() -> bool { + true + } fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { self.to_def_id().to_fingerprint(tcx) @@ -336,7 +342,10 @@ impl<'tcx> DepNodeParams> for LocalDefId { } impl<'tcx> DepNodeParams> for CrateNum { - const CAN_RECONSTRUCT_QUERY_KEY: bool = true; + #[inline] + fn can_reconstruct_query_key() -> bool { + true + } fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX }; @@ -353,7 +362,10 @@ impl<'tcx> DepNodeParams> for CrateNum { } impl<'tcx> DepNodeParams> for (DefId, DefId) { - const CAN_RECONSTRUCT_QUERY_KEY: bool = false; + #[inline] + fn can_reconstruct_query_key() -> bool { + false + } // We actually would not need to specialize the implementation of this // method but it's faster to combine the hashes than to instantiate a full @@ -375,7 +387,10 @@ impl<'tcx> DepNodeParams> for (DefId, DefId) { } impl<'tcx> DepNodeParams> for HirId { - const CAN_RECONSTRUCT_QUERY_KEY: bool = false; + #[inline] + fn can_reconstruct_query_key() -> bool { + false + } // We actually would not need to specialize the implementation of this // method but it's faster to combine the hashes than to instantiate a full diff --git a/src/librustc_middle/lib.rs b/src/librustc_middle/lib.rs index 7c433574d1843..62c92e988ba60 100644 --- a/src/librustc_middle/lib.rs +++ b/src/librustc_middle/lib.rs @@ -42,7 +42,7 @@ #![feature(option_expect_none)] #![feature(or_patterns)] #![feature(range_is_empty)] -#![feature(specialization)] // FIXME: min_specialization does not work +#![feature(min_specialization)] #![feature(track_caller)] #![feature(trusted_len)] #![feature(vec_remove_item)] diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs index 98973f1b6fb7d..f159b82536fe2 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -457,8 +457,39 @@ impl ClearCrossCrate { } } -impl rustc_serialize::UseSpecializedEncodable for ClearCrossCrate {} -impl rustc_serialize::UseSpecializedDecodable for ClearCrossCrate {} +const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0; +const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1; + +impl rustc_serialize::UseSpecializedEncodable for ClearCrossCrate { + #[inline] + fn default_encode(&self, e: &mut E) -> Result<(), E::Error> { + match *self { + ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(e), + ClearCrossCrate::Set(ref val) => { + TAG_CLEAR_CROSS_CRATE_SET.encode(e)?; + val.encode(e) + } + } + } +} +impl rustc_serialize::UseSpecializedDecodable for ClearCrossCrate { + #[inline] + fn default_decode(d: &mut D) -> Result, D::Error> + where + D: rustc_serialize::Decoder, + { + let discr = u8::decode(d)?; + + match discr { + TAG_CLEAR_CROSS_CRATE_CLEAR => Ok(ClearCrossCrate::Clear), + TAG_CLEAR_CROSS_CRATE_SET => { + let val = T::decode(d)?; + Ok(ClearCrossCrate::Set(val)) + } + _ => unreachable!(), + } + } +} /// Grouped information about the source code origin of a MIR entity. /// Intended to be inspected by diagnostics and debuginfo. @@ -1952,8 +1983,6 @@ impl ProjectionElem { /// and the index is a local. pub type PlaceElem<'tcx> = ProjectionElem>; -impl<'tcx> Copy for PlaceElem<'tcx> {} - // At least on 64 bit systems, `PlaceElem` should not be larger than two pointers. #[cfg(target_arch = "x86_64")] static_assert_size!(PlaceElem<'_>, 16); diff --git a/src/librustc_middle/ty/codec.rs b/src/librustc_middle/ty/codec.rs index 8bc69a9d12312..1a8e5c45dd2f7 100644 --- a/src/librustc_middle/ty/codec.rs +++ b/src/librustc_middle/ty/codec.rs @@ -97,7 +97,7 @@ where pub fn encode_spanned_predicates<'tcx, E, C>( encoder: &mut E, - predicates: &'tcx [(ty::Predicate<'tcx>, Span)], + predicates: &[(ty::Predicate<'tcx>, Span)], cache: C, ) -> Result<(), E::Error> where @@ -139,7 +139,7 @@ pub trait TyDecoder<'tcx>: Decoder { } #[inline] -pub fn decode_arena_allocable( +pub fn decode_arena_allocable<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>( decoder: &mut D, ) -> Result<&'tcx T, D::Error> where @@ -149,7 +149,7 @@ where } #[inline] -pub fn decode_arena_allocable_slice( +pub fn decode_arena_allocable_slice<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>( decoder: &mut D, ) -> Result<&'tcx [T], D::Error> where @@ -318,18 +318,38 @@ macro_rules! __impl_decoder_methods { macro_rules! impl_arena_allocatable_decoder { ([]$args:tt) => {}; ([decode $(, $attrs:ident)*] - [[$DecoderName:ident [$($typaram:tt),*]], [$name:ident: $ty:ty], $tcx:lifetime]) => { - impl<$($typaram),*> SpecializedDecoder<&$tcx $ty> for $DecoderName<$($typaram),*> { + [[$DecoderName:ident [$($typaram:tt),*]], [$name:ident: $ty:ty, $gen_ty:ty], $tcx:lifetime]) => { + // FIXME(#36588): These impls are horribly unsound as they allow + // the caller to pick any lifetime for `'tcx`, including `'static`. + #[allow(unused_lifetimes)] + impl<'_x, '_y, '_z, '_w, '_a, $($typaram),*> SpecializedDecoder<&'_a $gen_ty> + for $DecoderName<$($typaram),*> + where &'_a $gen_ty: UseSpecializedDecodable + { #[inline] - fn specialized_decode(&mut self) -> Result<&$tcx $ty, Self::Error> { - decode_arena_allocable(self) + fn specialized_decode(&mut self) -> Result<&'_a $gen_ty, Self::Error> { + unsafe { + std::mem::transmute::< + Result<&$tcx $ty, Self::Error>, + Result<&'_a $gen_ty, Self::Error>, + >(decode_arena_allocable(self)) + } } } - impl<$($typaram),*> SpecializedDecoder<&$tcx [$ty]> for $DecoderName<$($typaram),*> { + #[allow(unused_lifetimes)] + impl<'_x, '_y, '_z, '_w, '_a, $($typaram),*> SpecializedDecoder<&'_a [$gen_ty]> + for $DecoderName<$($typaram),*> + where &'_a [$gen_ty]: UseSpecializedDecodable + { #[inline] - fn specialized_decode(&mut self) -> Result<&$tcx [$ty], Self::Error> { - decode_arena_allocable_slice(self) + fn specialized_decode(&mut self) -> Result<&'_a [$gen_ty], Self::Error> { + unsafe { + std::mem::transmute::< + Result<&$tcx [$ty], Self::Error>, + Result<&'_a [$gen_ty], Self::Error>, + >(decode_arena_allocable_slice(self)) + } } } }; @@ -340,9 +360,9 @@ macro_rules! impl_arena_allocatable_decoder { #[macro_export] macro_rules! impl_arena_allocatable_decoders { - ($args:tt, [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => { + ($args:tt, [$($a:tt $name:ident: $ty:ty, $gen_ty:ty;)*], $tcx:lifetime) => { $( - impl_arena_allocatable_decoder!($a [$args, [$name: $ty], $tcx]); + impl_arena_allocatable_decoder!($a [$args, [$name: $ty, $gen_ty], $tcx]); )* } } @@ -352,14 +372,15 @@ macro_rules! implement_ty_decoder { ($DecoderName:ident <$($typaram:tt),*>) => { mod __ty_decoder_impl { use std::borrow::Cow; + use std::mem::transmute; - use rustc_serialize::{Decoder, SpecializedDecoder}; + use rustc_serialize::{Decoder, SpecializedDecoder, UseSpecializedDecodable}; use $crate::infer::canonical::CanonicalVarInfos; use $crate::ty; use $crate::ty::codec::*; - use $crate::ty::subst::SubstsRef; - use rustc_hir::def_id::{CrateNum}; + use $crate::ty::subst::InternalSubsts; + use rustc_hir::def_id::CrateNum; use rustc_span::Span; @@ -398,8 +419,7 @@ macro_rules! implement_ty_decoder { } // FIXME(#36588): These impls are horribly unsound as they allow - // the caller to pick any lifetime for `'tcx`, including `'static`, - // by using the unspecialized proxies to them. + // the caller to pick any lifetime for `'tcx`, including `'static`. rustc_hir::arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx); arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx); @@ -411,90 +431,98 @@ macro_rules! implement_ty_decoder { } } - impl<$($typaram),*> SpecializedDecoder> - for $DecoderName<$($typaram),*> { - fn specialized_decode(&mut self) -> Result, Self::Error> { - decode_ty(self) + impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x ty::TyS<'_y>> + for $DecoderName<$($typaram),*> + where &'_x ty::TyS<'_y>: UseSpecializedDecodable + { + fn specialized_decode(&mut self) -> Result<&'_x ty::TyS<'_y>, Self::Error> { + unsafe { transmute::, Self::Error>, Result<&'_x ty::TyS<'_y>, Self::Error>>(decode_ty(self)) } } } - impl<$($typaram),*> SpecializedDecoder<&'tcx [(ty::Predicate<'tcx>, Span)]> - for $DecoderName<$($typaram),*> { + impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x [(ty::Predicate<'_y>, Span)]> + for $DecoderName<$($typaram),*> + where &'_x [(ty::Predicate<'_y>, Span)]: UseSpecializedDecodable { fn specialized_decode(&mut self) - -> Result<&'tcx [(ty::Predicate<'tcx>, Span)], Self::Error> { - decode_spanned_predicates(self) + -> Result<&'_x [(ty::Predicate<'_y>, Span)], Self::Error> + { + unsafe { transmute(decode_spanned_predicates(self)) } } } - impl<$($typaram),*> SpecializedDecoder> - for $DecoderName<$($typaram),*> { - fn specialized_decode(&mut self) -> Result, Self::Error> { - decode_substs(self) + impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x InternalSubsts<'_y>> + for $DecoderName<$($typaram),*> + where &'_x InternalSubsts<'_y>: UseSpecializedDecodable { + fn specialized_decode(&mut self) -> Result<&'_x InternalSubsts<'_y>, Self::Error> { + unsafe { transmute(decode_substs(self)) } } } - impl<$($typaram),*> SpecializedDecoder<$crate::mir::Place<'tcx>> + impl<'_x, $($typaram),*> SpecializedDecoder<$crate::mir::Place<'_x>> for $DecoderName<$($typaram),*> { fn specialized_decode( &mut self - ) -> Result<$crate::mir::Place<'tcx>, Self::Error> { - decode_place(self) + ) -> Result<$crate::mir::Place<'_x>, Self::Error> { + unsafe { transmute(decode_place(self)) } } } - impl<$($typaram),*> SpecializedDecoder> + impl<'_x, $($typaram),*> SpecializedDecoder> for $DecoderName<$($typaram),*> { - fn specialized_decode(&mut self) -> Result, Self::Error> { - decode_region(self) + fn specialized_decode(&mut self) -> Result, Self::Error> { + unsafe { transmute(decode_region(self)) } } } - impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List>> - for $DecoderName<$($typaram),*> { + impl<'_x, '_y, '_z, $($typaram),*> SpecializedDecoder<&'_x ty::List<&'_y ty::TyS<'_z>>> + for $DecoderName<$($typaram),*> + where &'_x ty::List<&'_y ty::TyS<'_z>>: UseSpecializedDecodable { fn specialized_decode(&mut self) - -> Result<&'tcx ty::List>, Self::Error> { - decode_ty_slice(self) + -> Result<&'_x ty::List<&'_y ty::TyS<'_z>>, Self::Error> { + unsafe { transmute(decode_ty_slice(self)) } } } - impl<$($typaram),*> SpecializedDecoder<&'tcx ty::AdtDef> + impl<'_x, $($typaram),*> SpecializedDecoder<&'_x ty::AdtDef> for $DecoderName<$($typaram),*> { - fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> { - decode_adt_def(self) + fn specialized_decode(&mut self) -> Result<&'_x ty::AdtDef, Self::Error> { + unsafe { transmute(decode_adt_def(self)) } } } - impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List>> - for $DecoderName<$($typaram),*> { + impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x ty::List>> + for $DecoderName<$($typaram),*> + where &'_x ty::List>: UseSpecializedDecodable { fn specialized_decode(&mut self) - -> Result<&'tcx ty::List>, Self::Error> { - decode_existential_predicate_slice(self) + -> Result<&'_x ty::List>, Self::Error> { + unsafe { transmute(decode_existential_predicate_slice(self)) } } } - impl<$($typaram),*> SpecializedDecoder> + impl<'_x, $($typaram),*> SpecializedDecoder> for $DecoderName<$($typaram),*> { fn specialized_decode(&mut self) - -> Result, Self::Error> { - decode_canonical_var_infos(self) + -> Result, Self::Error> { + unsafe { transmute(decode_canonical_var_infos(self)) } } } - impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>> - for $DecoderName<$($typaram),*> { - fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { - decode_const(self) + impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x $crate::ty::Const<'_y>> + for $DecoderName<$($typaram),*> + where &'_x $crate::ty::Const<'_y>: UseSpecializedDecodable { + fn specialized_decode(&mut self) -> Result<&'_x ty::Const<'_y>, Self::Error> { + unsafe { transmute(decode_const(self)) } } } - impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::mir::interpret::Allocation> + impl<'_x, $($typaram),*> SpecializedDecoder<&'_x $crate::mir::interpret::Allocation> for $DecoderName<$($typaram),*> { fn specialized_decode( &mut self - ) -> Result<&'tcx $crate::mir::interpret::Allocation, Self::Error> { - decode_allocation(self) + ) -> Result<&'_x $crate::mir::interpret::Allocation, Self::Error> { + unsafe { transmute(decode_allocation(self)) } } } } - } + }; } diff --git a/src/librustc_middle/ty/query/on_disk_cache.rs b/src/librustc_middle/ty/query/on_disk_cache.rs index 4eae06742d9d3..5374dff422425 100644 --- a/src/librustc_middle/ty/query/on_disk_cache.rs +++ b/src/librustc_middle/ty/query/on_disk_cache.rs @@ -1,6 +1,6 @@ use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; +use crate::mir::interpret; use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState}; -use crate::mir::{self, interpret}; use crate::ty::codec::{self as ty_codec, TyDecoder, TyEncoder}; use crate::ty::context::TyCtxt; use crate::ty::{self, Ty}; @@ -26,9 +26,6 @@ use std::mem; const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE; -const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0; -const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1; - const TAG_NO_EXPN_DATA: u8 = 0; const TAG_EXPN_DATA_SHORTHAND: u8 = 1; const TAG_EXPN_DATA_INLINE: u8 = 2; @@ -667,24 +664,6 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { } } -impl<'a, 'tcx, T: Decodable> SpecializedDecoder> - for CacheDecoder<'a, 'tcx> -{ - #[inline] - fn specialized_decode(&mut self) -> Result, Self::Error> { - let discr = u8::decode(self)?; - - match discr { - TAG_CLEAR_CROSS_CRATE_CLEAR => Ok(mir::ClearCrossCrate::Clear), - TAG_CLEAR_CROSS_CRATE_SET => { - let val = T::decode(self)?; - Ok(mir::ClearCrossCrate::Set(val)) - } - _ => unreachable!(), - } - } -} - //- ENCODING ------------------------------------------------------------------- /// An encoder that can write the incr. comp. cache. @@ -828,17 +807,20 @@ where } } -impl<'a, 'tcx, E> SpecializedEncoder> for CacheEncoder<'a, 'tcx, E> +impl<'a, 'b, 'c, 'tcx, E> SpecializedEncoder<&'b ty::TyS<'c>> for CacheEncoder<'a, 'tcx, E> where E: 'a + TyEncoder, + &'b ty::TyS<'c>: UseSpecializedEncodable, { #[inline] - fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> { + fn specialized_encode(&mut self, ty: &&'b ty::TyS<'c>) -> Result<(), Self::Error> { + debug_assert!(self.tcx.lift(ty).is_some()); + let ty = unsafe { std::mem::transmute::<&&'b ty::TyS<'c>, &&'tcx ty::TyS<'tcx>>(ty) }; ty_codec::encode_with_shorthand(self, ty, |encoder| &mut encoder.type_shorthands) } } -impl<'a, 'tcx, E> SpecializedEncoder<&'tcx [(ty::Predicate<'tcx>, Span)]> +impl<'a, 'b, 'c, 'tcx, E> SpecializedEncoder<&'b [(ty::Predicate<'c>, Span)]> for CacheEncoder<'a, 'tcx, E> where E: 'a + TyEncoder, @@ -846,8 +828,15 @@ where #[inline] fn specialized_encode( &mut self, - predicates: &&'tcx [(ty::Predicate<'tcx>, Span)], + predicates: &&'b [(ty::Predicate<'c>, Span)], ) -> Result<(), Self::Error> { + debug_assert!(self.tcx.lift(*predicates).is_some()); + let predicates = unsafe { + std::mem::transmute::< + &&'b [(ty::Predicate<'c>, Span)], + &&'tcx [(ty::Predicate<'tcx>, Span)], + >(predicates) + }; ty_codec::encode_spanned_predicates(self, predicates, |encoder| { &mut encoder.predicate_shorthands }) @@ -890,23 +879,6 @@ impl<'a, 'tcx> SpecializedEncoder for CacheEncoder<'a, 'tcx, opaque } } -impl<'a, 'tcx, E, T> SpecializedEncoder> for CacheEncoder<'a, 'tcx, E> -where - E: 'a + TyEncoder, - T: Encodable, -{ - #[inline] - fn specialized_encode(&mut self, val: &mir::ClearCrossCrate) -> Result<(), Self::Error> { - match *val { - mir::ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(self), - mir::ClearCrossCrate::Set(ref val) => { - TAG_CLEAR_CROSS_CRATE_SET.encode(self)?; - val.encode(self) - } - } - } -} - macro_rules! encoder_methods { ($($name:ident($ty:ty);)*) => { #[inline] @@ -995,7 +967,7 @@ fn encode_query_results<'a, 'tcx, Q, E>( query_result_index: &mut EncodedQueryResultIndex, ) -> Result<(), E::Error> where - Q: super::QueryDescription>, + Q: super::QueryDescription> + super::QueryAccessors>, Q::Value: Encodable, E: 'a + TyEncoder, { diff --git a/src/librustc_middle/ty/query/profiling_support.rs b/src/librustc_middle/ty/query/profiling_support.rs index e0d3e764dad83..3c44662441890 100644 --- a/src/librustc_middle/ty/query/profiling_support.rs +++ b/src/librustc_middle/ty/query/profiling_support.rs @@ -112,30 +112,53 @@ impl IntoSelfProfilingString for T { } } -impl IntoSelfProfilingString for DefId { +impl IntoSelfProfilingString for T { fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId { + self.spec_to_self_profile_string(builder) + } +} + +#[rustc_specialization_trait] +pub trait SpecIntoSelfProfilingString: Debug { + fn spec_to_self_profile_string( + &self, + builder: &mut QueryKeyStringBuilder<'_, '_, '_>, + ) -> StringId; +} + +impl SpecIntoSelfProfilingString for DefId { + fn spec_to_self_profile_string( + &self, + builder: &mut QueryKeyStringBuilder<'_, '_, '_>, + ) -> StringId { builder.def_id_to_string_id(*self) } } -impl IntoSelfProfilingString for CrateNum { - fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId { +impl SpecIntoSelfProfilingString for CrateNum { + fn spec_to_self_profile_string( + &self, + builder: &mut QueryKeyStringBuilder<'_, '_, '_>, + ) -> StringId { builder.def_id_to_string_id(DefId { krate: *self, index: CRATE_DEF_INDEX }) } } -impl IntoSelfProfilingString for DefIndex { - fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId { +impl SpecIntoSelfProfilingString for DefIndex { + fn spec_to_self_profile_string( + &self, + builder: &mut QueryKeyStringBuilder<'_, '_, '_>, + ) -> StringId { builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: *self }) } } -impl IntoSelfProfilingString for (T0, T1) +impl SpecIntoSelfProfilingString for (T0, T1) where - T0: IntoSelfProfilingString + Debug, - T1: IntoSelfProfilingString + Debug, + T0: SpecIntoSelfProfilingString, + T1: SpecIntoSelfProfilingString, { - default fn to_self_profile_string( + fn spec_to_self_profile_string( &self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>, ) -> StringId { diff --git a/src/librustc_middle/ty/query/values.rs b/src/librustc_middle/ty/query/values.rs index b01d15c29b2db..b1f76ff6a03bd 100644 --- a/src/librustc_middle/ty/query/values.rs +++ b/src/librustc_middle/ty/query/values.rs @@ -1,4 +1,4 @@ -use crate::ty::{self, AdtSizedConstraint, Ty, TyCtxt}; +use crate::ty::{self, AdtSizedConstraint, Ty, TyCtxt, TyS}; use rustc_span::symbol::Symbol; @@ -13,9 +13,11 @@ impl<'tcx, T> Value<'tcx> for T { } } -impl<'tcx> Value<'tcx> for Ty<'tcx> { - fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - tcx.types.err +impl<'tcx> Value<'tcx> for &'_ TyS<'_> { + fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self { + // SAFETY: This is never called when `Self` is not `Ty<'tcx>`. + // FIXME: Represent the above fact in the trait system somehow. + unsafe { std::mem::transmute::, Ty<'_>>(tcx.types.err) } } } @@ -25,8 +27,14 @@ impl<'tcx> Value<'tcx> for ty::SymbolName { } } -impl<'tcx> Value<'tcx> for AdtSizedConstraint<'tcx> { +impl<'tcx> Value<'tcx> for AdtSizedConstraint<'_> { fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self { - AdtSizedConstraint(tcx.intern_type_list(&[tcx.types.err])) + // SAFETY: This is never called when `Self` is not `AdtSizedConstraint<'tcx>`. + // FIXME: Represent the above fact in the trait system somehow. + unsafe { + std::mem::transmute::, AdtSizedConstraint<'_>>( + AdtSizedConstraint(tcx.intern_type_list(&[tcx.types.err])), + ) + } } } diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index 5d4c2a54267c3..34333382a22a8 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -2404,8 +2404,6 @@ impl<'tcx> Const<'tcx> { } } -impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {} - /// Represents a constant in Rust. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)] #[derive(HashStable)] diff --git a/src/librustc_query_system/dep_graph/dep_node.rs b/src/librustc_query_system/dep_graph/dep_node.rs index d8875f8ac64a2..002b0f9c165dd 100644 --- a/src/librustc_query_system/dep_graph/dep_node.rs +++ b/src/librustc_query_system/dep_graph/dep_node.rs @@ -91,7 +91,7 @@ impl fmt::Debug for DepNode { } pub trait DepNodeParams: fmt::Debug + Sized { - const CAN_RECONSTRUCT_QUERY_KEY: bool; + fn can_reconstruct_query_key() -> bool; /// This method turns the parameters of a DepNodeConstructor into an opaque /// Fingerprint to be used in DepNode. @@ -108,7 +108,7 @@ pub trait DepNodeParams: fmt::Debug + Sized { /// This method tries to recover the query key from the given `DepNode`, /// something which is needed when forcing `DepNode`s during red-green /// evaluation. The query system will only call this method if - /// `CAN_RECONSTRUCT_QUERY_KEY` is `true`. + /// `can_reconstruct_query_key()` is `true`. /// It is always valid to return `None` here, in which case incremental /// compilation will treat the query as having changed instead of forcing it. fn recover(tcx: Ctxt, dep_node: &DepNode) -> Option; @@ -118,7 +118,10 @@ impl DepNodeParams for T where T: HashStable + fmt::Debug, { - default const CAN_RECONSTRUCT_QUERY_KEY: bool = false; + #[inline] + default fn can_reconstruct_query_key() -> bool { + false + } default fn to_fingerprint(&self, tcx: Ctxt) -> Fingerprint { let mut hcx = tcx.create_stable_hashing_context(); diff --git a/src/librustc_query_system/lib.rs b/src/librustc_query_system/lib.rs index 8e350d3ba267e..12450a4ccd3eb 100644 --- a/src/librustc_query_system/lib.rs +++ b/src/librustc_query_system/lib.rs @@ -4,7 +4,7 @@ #![feature(const_panic)] #![feature(core_intrinsics)] #![feature(hash_raw_entry)] -#![feature(specialization)] // FIXME: min_specialization rejects `default const` +#![feature(min_specialization)] #![feature(stmt_expr_attributes)] #![feature(vec_remove_item)] diff --git a/src/librustc_serialize/lib.rs b/src/librustc_serialize/lib.rs index 7261d631a6f31..3dc3e78382096 100644 --- a/src/librustc_serialize/lib.rs +++ b/src/librustc_serialize/lib.rs @@ -10,7 +10,7 @@ Core encoding and decoding interfaces. test(attr(allow(unused_variables), deny(warnings))) )] #![feature(box_syntax)] -#![feature(specialization)] // FIXME: min_specialization does not work +#![feature(min_specialization)] #![feature(never_type)] #![feature(nll)] #![feature(associated_type_bounds)] diff --git a/src/librustc_serialize/serialize.rs b/src/librustc_serialize/serialize.rs index e80d16bb0c7ab..29c5737ad895a 100644 --- a/src/librustc_serialize/serialize.rs +++ b/src/librustc_serialize/serialize.rs @@ -635,24 +635,6 @@ impl Decodable for PhantomData { } } -impl<'a, T: ?Sized + Encodable> Encodable for &'a T { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - (**self).encode(s) - } -} - -impl Encodable for Box { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - (**self).encode(s) - } -} - -impl Decodable for Box { - fn decode(d: &mut D) -> Result, D::Error> { - Ok(box Decodable::decode(d)?) - } -} - impl Decodable for Box<[T]> { fn decode(d: &mut D) -> Result, D::Error> { let v: Vec = Decodable::decode(d)?; @@ -1008,8 +990,20 @@ impl Decodable for T { // for this exact reason. // May be fixable in a simpler fashion via the // more complex lattice model for specialization. -impl<'a, T: ?Sized + Encodable> UseSpecializedEncodable for &'a T {} -impl UseSpecializedEncodable for Box {} -impl UseSpecializedDecodable for Box {} +impl<'a, T: ?Sized + Encodable> UseSpecializedEncodable for &'a T { + fn default_encode(&self, s: &mut S) -> Result<(), S::Error> { + (**self).encode(s) + } +} +impl UseSpecializedEncodable for Box { + fn default_encode(&self, s: &mut S) -> Result<(), S::Error> { + (**self).encode(s) + } +} +impl UseSpecializedDecodable for Box { + fn default_decode(d: &mut D) -> Result, D::Error> { + Ok(box Decodable::decode(d)?) + } +} impl<'a, T: Decodable> UseSpecializedDecodable for &'a T {} impl<'a, T: Decodable> UseSpecializedDecodable for &'a [T] {} diff --git a/src/librustc_trait_selection/infer.rs b/src/librustc_trait_selection/infer.rs index 66df4fe951162..f244785b49d2f 100644 --- a/src/librustc_trait_selection/infer.rs +++ b/src/librustc_trait_selection/infer.rs @@ -90,7 +90,7 @@ pub trait InferCtxtBuilderExt<'tcx> { where K: TypeFoldable<'tcx>, R: Debug + TypeFoldable<'tcx>, - Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable; + Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>; } impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> { @@ -118,7 +118,7 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> { where K: TypeFoldable<'tcx>, R: Debug + TypeFoldable<'tcx>, - Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable, + Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>, { self.enter_with_canonical( DUMMY_SP, From c29b3fa1484c625bd34cb4d94fc76f36c6233447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 29 May 2020 09:24:59 -0700 Subject: [PATCH 20/45] On recursive ADT, provide indirection structured suggestion --- src/librustc_errors/diagnostic.rs | 23 +++++++ src/librustc_errors/diagnostic_builder.rs | 13 ++++ src/librustc_middle/ty/util.rs | 10 ++- .../traits/error_reporting/mod.rs | 66 +++++++++++++++---- src/librustc_typeck/check/mod.rs | 6 +- .../infinite-tag-type-recursion.stderr | 9 ++- src/test/ui/issues/issue-17431-1.stderr | 11 +++- src/test/ui/issues/issue-17431-2.stderr | 22 +++++-- src/test/ui/issues/issue-17431-3.stderr | 11 +++- src/test/ui/issues/issue-17431-4.stderr | 11 +++- src/test/ui/issues/issue-17431-5.stderr | 11 +++- src/test/ui/issues/issue-17431-6.stderr | 9 ++- src/test/ui/issues/issue-17431-7.stderr | 9 ++- src/test/ui/issues/issue-2718-a.stderr | 9 ++- src/test/ui/issues/issue-3008-1.stderr | 9 ++- src/test/ui/issues/issue-3008-2.stderr | 11 +++- src/test/ui/issues/issue-3008-3.stderr | 9 ++- src/test/ui/issues/issue-32326.stderr | 5 +- src/test/ui/issues/issue-3779.stderr | 11 +++- src/test/ui/issues/issue-57271.stderr | 18 ++++- src/test/ui/recursion/recursive-enum.stderr | 9 ++- src/test/ui/sized-cycle-note.stderr | 22 +++++-- src/test/ui/span/E0072.stderr | 11 +++- src/test/ui/span/multiline-span-E0072.stderr | 11 +++- src/test/ui/span/recursive-type-field.stderr | 23 ++++--- src/test/ui/type/type-recursive.stderr | 11 +++- .../ui/union/union-nonrepresentable.stderr | 11 +++- 27 files changed, 315 insertions(+), 66 deletions(-) diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index cff83c3d5cda2..acaa26c6ad2fc 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -296,6 +296,29 @@ impl Diagnostic { self } + pub fn multipart_suggestions( + &mut self, + msg: &str, + suggestions: Vec>, + applicability: Applicability, + ) -> &mut Self { + self.suggestions.push(CodeSuggestion { + substitutions: suggestions + .into_iter() + .map(|suggestion| Substitution { + parts: suggestion + .into_iter() + .map(|(span, snippet)| SubstitutionPart { snippet, span }) + .collect(), + }) + .collect(), + msg: msg.to_owned(), + style: SuggestionStyle::ShowCode, + applicability, + }); + self + } + /// Prints out a message with for a multipart suggestion without showing the suggested code. /// /// This is intended to be used for suggestions that are obvious in what the changes need to diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 2dbd9f4e52fad..22bf8fe34aa15 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -260,6 +260,19 @@ impl<'a> DiagnosticBuilder<'a> { self } + pub fn multipart_suggestions( + &mut self, + msg: &str, + suggestions: Vec>, + applicability: Applicability, + ) -> &mut Self { + if !self.0.allow_suggestions { + return self; + } + self.0.diagnostic.multipart_suggestions(msg, suggestions, applicability); + self + } + pub fn tool_only_multipart_suggestion( &mut self, msg: &str, diff --git a/src/librustc_middle/ty/util.rs b/src/librustc_middle/ty/util.rs index c2b794ca4bdd9..5cdfa6f90128d 100644 --- a/src/librustc_middle/ty/util.rs +++ b/src/librustc_middle/ty/util.rs @@ -827,7 +827,15 @@ impl<'tcx> ty::TyS<'tcx> { // Find non representable fields with their spans fold_repr(def.all_fields().map(|field| { let ty = field.ty(tcx, substs); - let span = tcx.hir().span_if_local(field.did).unwrap_or(sp); + let span = match field + .did + .as_local() + .map(|id| tcx.hir().as_local_hir_id(id)) + .and_then(|id| tcx.hir().find(id)) + { + Some(hir::Node::Field(field)) => field.ty.span, + _ => sp, + }; match is_type_structurally_recursive( tcx, span, diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index 1b72a4bf84f19..3457f7b4580c5 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -1747,24 +1747,62 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { pub fn recursive_type_with_infinite_size_error( tcx: TyCtxt<'tcx>, type_def_id: DefId, -) -> DiagnosticBuilder<'tcx> { + spans: Vec, +) { assert!(type_def_id.is_local()); let span = tcx.hir().span_if_local(type_def_id).unwrap(); let span = tcx.sess.source_map().guess_head_span(span); - let mut err = struct_span_err!( - tcx.sess, - span, - E0072, - "recursive type `{}` has infinite size", - tcx.def_path_str(type_def_id) - ); + let path = tcx.def_path_str(type_def_id); + let mut err = + struct_span_err!(tcx.sess, span, E0072, "recursive type `{}` has infinite size", path); err.span_label(span, "recursive type has infinite size"); - err.help(&format!( - "insert indirection (e.g., a `Box`, `Rc`, or `&`) \ - at some point to make `{}` representable", - tcx.def_path_str(type_def_id) - )); - err + for &span in &spans { + err.span_label(span, "recursive without indirection"); + } + let short_msg = format!("insert some indirection to make `{}` representable", path); + let msg = format!( + "insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `{}` representable", + path, + ); + match &spans[..] { + [span] => { + err.multipart_suggestions( + &short_msg, + vec![ + vec![ + (span.shrink_to_lo(), "Box<".to_string()), + (span.shrink_to_hi(), ">".to_string()), + ], + vec![ + (span.shrink_to_lo(), "Rc<".to_string()), + (span.shrink_to_hi(), ">".to_string()), + ], + vec![(span.shrink_to_lo(), "&".to_string())], + ], + Applicability::HasPlaceholders, + ); + } + _ if spans.len() <= 4 => { + err.multipart_suggestion( + &msg, + spans + .iter() + .flat_map(|&span| { + vec![ + (span.shrink_to_lo(), "Box<".to_string()), + (span.shrink_to_hi(), ">".to_string()), + ] + .into_iter() + }) + .collect(), + Applicability::HasPlaceholders, + ); + } + _ => { + err.help(&msg); + } + } + err.emit(); } /// Summarizes information diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f2aeed4f1e465..1e8a149d7d9ec 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2390,11 +2390,7 @@ fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: LocalDefId) -> bo // caught by case 1. match rty.is_representable(tcx, sp) { Representability::SelfRecursive(spans) => { - let mut err = recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id()); - for span in spans { - err.span_label(span, "recursive without indirection"); - } - err.emit(); + recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id(), spans); return false; } Representability::Representable | Representability::ContainsRecursive => (), diff --git a/src/test/ui/infinite/infinite-tag-type-recursion.stderr b/src/test/ui/infinite/infinite-tag-type-recursion.stderr index 11f82b842ba6f..b6a4d8f4cf563 100644 --- a/src/test/ui/infinite/infinite-tag-type-recursion.stderr +++ b/src/test/ui/infinite/infinite-tag-type-recursion.stderr @@ -6,7 +6,14 @@ LL | enum MList { Cons(isize, MList), Nil } | | | recursive type has infinite size | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `MList` representable +help: insert some indirection to make `MList` representable + | +LL | enum MList { Cons(isize, Box), Nil } + | ^^^^ ^ +LL | enum MList { Cons(isize, Rc), Nil } + | ^^^ ^ +LL | enum MList { Cons(isize, &MList), Nil } + | ^ error[E0391]: cycle detected when computing drop-check constraints for `MList` --> $DIR/infinite-tag-type-recursion.rs:1:1 diff --git a/src/test/ui/issues/issue-17431-1.stderr b/src/test/ui/issues/issue-17431-1.stderr index eb5a1366e8953..8d44154650e04 100644 --- a/src/test/ui/issues/issue-17431-1.stderr +++ b/src/test/ui/issues/issue-17431-1.stderr @@ -2,11 +2,18 @@ error[E0072]: recursive type `Foo` has infinite size --> $DIR/issue-17431-1.rs:1:1 | LL | struct Foo { foo: Option> } - | ^^^^^^^^^^ ------------------------ recursive without indirection + | ^^^^^^^^^^ ------------------- recursive without indirection | | | recursive type has infinite size | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable +help: insert some indirection to make `Foo` representable + | +LL | struct Foo { foo: Box>> } + | ^^^^ ^ +LL | struct Foo { foo: Rc>> } + | ^^^ ^ +LL | struct Foo { foo: &Option> } + | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17431-2.stderr b/src/test/ui/issues/issue-17431-2.stderr index 3a7b0e9ce7997..b06184e84da28 100644 --- a/src/test/ui/issues/issue-17431-2.stderr +++ b/src/test/ui/issues/issue-17431-2.stderr @@ -2,21 +2,35 @@ error[E0072]: recursive type `Baz` has infinite size --> $DIR/issue-17431-2.rs:1:1 | LL | struct Baz { q: Option } - | ^^^^^^^^^^ -------------- recursive without indirection + | ^^^^^^^^^^ ----------- recursive without indirection | | | recursive type has infinite size | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Baz` representable +help: insert some indirection to make `Baz` representable + | +LL | struct Baz { q: Box> } + | ^^^^ ^ +LL | struct Baz { q: Rc> } + | ^^^ ^ +LL | struct Baz { q: &Option } + | ^ error[E0072]: recursive type `Foo` has infinite size --> $DIR/issue-17431-2.rs:4:1 | LL | struct Foo { q: Option } - | ^^^^^^^^^^ -------------- recursive without indirection + | ^^^^^^^^^^ ----------- recursive without indirection | | | recursive type has infinite size | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable +help: insert some indirection to make `Foo` representable + | +LL | struct Foo { q: Box> } + | ^^^^ ^ +LL | struct Foo { q: Rc> } + | ^^^ ^ +LL | struct Foo { q: &Option } + | ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-17431-3.stderr b/src/test/ui/issues/issue-17431-3.stderr index 675a2e2714209..f32bd70fd6d94 100644 --- a/src/test/ui/issues/issue-17431-3.stderr +++ b/src/test/ui/issues/issue-17431-3.stderr @@ -2,11 +2,18 @@ error[E0072]: recursive type `Foo` has infinite size --> $DIR/issue-17431-3.rs:3:1 | LL | struct Foo { foo: Mutex> } - | ^^^^^^^^^^ ----------------------- recursive without indirection + | ^^^^^^^^^^ ------------------ recursive without indirection | | | recursive type has infinite size | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable +help: insert some indirection to make `Foo` representable + | +LL | struct Foo { foo: Box>> } + | ^^^^ ^ +LL | struct Foo { foo: Rc>> } + | ^^^ ^ +LL | struct Foo { foo: &Mutex> } + | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17431-4.stderr b/src/test/ui/issues/issue-17431-4.stderr index aff9071095ca0..372c5e975c844 100644 --- a/src/test/ui/issues/issue-17431-4.stderr +++ b/src/test/ui/issues/issue-17431-4.stderr @@ -2,11 +2,18 @@ error[E0072]: recursive type `Foo` has infinite size --> $DIR/issue-17431-4.rs:3:1 | LL | struct Foo { foo: Option>>, marker: marker::PhantomData } - | ^^^^^^^^^^^^^ --------------------------- recursive without indirection + | ^^^^^^^^^^^^^ ---------------------- recursive without indirection | | | recursive type has infinite size | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable +help: insert some indirection to make `Foo` representable + | +LL | struct Foo { foo: Box>>>, marker: marker::PhantomData } + | ^^^^ ^ +LL | struct Foo { foo: Rc>>>, marker: marker::PhantomData } + | ^^^ ^ +LL | struct Foo { foo: &Option>>, marker: marker::PhantomData } + | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17431-5.stderr b/src/test/ui/issues/issue-17431-5.stderr index 537f9f34f55ca..01b850ac33694 100644 --- a/src/test/ui/issues/issue-17431-5.stderr +++ b/src/test/ui/issues/issue-17431-5.stderr @@ -2,11 +2,18 @@ error[E0072]: recursive type `Bar` has infinite size --> $DIR/issue-17431-5.rs:5:1 | LL | struct Bar { x: Bar , marker: marker::PhantomData } - | ^^^^^^^^^^^^^ ----------- recursive without indirection + | ^^^^^^^^^^^^^ -------- recursive without indirection | | | recursive type has infinite size | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable +help: insert some indirection to make `Bar` representable + | +LL | struct Bar { x: Box> , marker: marker::PhantomData } + | ^^^^ ^ +LL | struct Bar { x: Rc> , marker: marker::PhantomData } + | ^^^ ^ +LL | struct Bar { x: &Bar , marker: marker::PhantomData } + | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17431-6.stderr b/src/test/ui/issues/issue-17431-6.stderr index cb2dab9501488..ce6c2db07fb6d 100644 --- a/src/test/ui/issues/issue-17431-6.stderr +++ b/src/test/ui/issues/issue-17431-6.stderr @@ -6,7 +6,14 @@ LL | enum Foo { X(Mutex>) } | | | recursive type has infinite size | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable +help: insert some indirection to make `Foo` representable + | +LL | enum Foo { X(Box>>) } + | ^^^^ ^ +LL | enum Foo { X(Rc>>) } + | ^^^ ^ +LL | enum Foo { X(&Mutex>) } + | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17431-7.stderr b/src/test/ui/issues/issue-17431-7.stderr index de70851da4b5f..4fb563ba502f2 100644 --- a/src/test/ui/issues/issue-17431-7.stderr +++ b/src/test/ui/issues/issue-17431-7.stderr @@ -6,7 +6,14 @@ LL | enum Foo { Voo(Option>) } | | | recursive type has infinite size | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable +help: insert some indirection to make `Foo` representable + | +LL | enum Foo { Voo(Box>>) } + | ^^^^ ^ +LL | enum Foo { Voo(Rc>>) } + | ^^^ ^ +LL | enum Foo { Voo(&Option>) } + | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-2718-a.stderr b/src/test/ui/issues/issue-2718-a.stderr index 0f52c79192843..48b7a61e059ea 100644 --- a/src/test/ui/issues/issue-2718-a.stderr +++ b/src/test/ui/issues/issue-2718-a.stderr @@ -7,7 +7,14 @@ LL | pub struct Pong(SendPacket); | | recursive without indirection | recursive type has infinite size | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `pingpong::Pong` representable +help: insert some indirection to make `pingpong::Pong` representable + | +LL | pub struct Pong(Box>); + | ^^^^ ^ +LL | pub struct Pong(Rc>); + | ^^^ ^ +LL | pub struct Pong(&SendPacket); + | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3008-1.stderr b/src/test/ui/issues/issue-3008-1.stderr index f12274134ee05..d1173a4b3334c 100644 --- a/src/test/ui/issues/issue-3008-1.stderr +++ b/src/test/ui/issues/issue-3008-1.stderr @@ -7,7 +7,14 @@ LL | enum Bar { LL | BarSome(Bar) | --- recursive without indirection | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable +help: insert some indirection to make `Bar` representable + | +LL | BarSome(Box) + | ^^^^ ^ +LL | BarSome(Rc) + | ^^^ ^ +LL | BarSome(&Bar) + | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3008-2.stderr b/src/test/ui/issues/issue-3008-2.stderr index acc15f4b57c73..4fd60639b21a8 100644 --- a/src/test/ui/issues/issue-3008-2.stderr +++ b/src/test/ui/issues/issue-3008-2.stderr @@ -2,11 +2,18 @@ error[E0072]: recursive type `Bar` has infinite size --> $DIR/issue-3008-2.rs:2:1 | LL | struct Bar { x: Bar } - | ^^^^^^^^^^ ------ recursive without indirection + | ^^^^^^^^^^ --- recursive without indirection | | | recursive type has infinite size | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable +help: insert some indirection to make `Bar` representable + | +LL | struct Bar { x: Box } + | ^^^^ ^ +LL | struct Bar { x: Rc } + | ^^^ ^ +LL | struct Bar { x: &Bar } + | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3008-3.stderr b/src/test/ui/issues/issue-3008-3.stderr index d08a3d9708db3..e6efad9188300 100644 --- a/src/test/ui/issues/issue-3008-3.stderr +++ b/src/test/ui/issues/issue-3008-3.stderr @@ -6,7 +6,14 @@ LL | enum E2 { V2(E2, marker::PhantomData), } | | | recursive type has infinite size | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `E2` representable +help: insert some indirection to make `E2` representable + | +LL | enum E2 { V2(Box>, marker::PhantomData), } + | ^^^^ ^ +LL | enum E2 { V2(Rc>, marker::PhantomData), } + | ^^^ ^ +LL | enum E2 { V2(&E2, marker::PhantomData), } + | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-32326.stderr b/src/test/ui/issues/issue-32326.stderr index 5967627e51a4b..0f3d3690b732e 100644 --- a/src/test/ui/issues/issue-32326.stderr +++ b/src/test/ui/issues/issue-32326.stderr @@ -8,7 +8,10 @@ LL | Plus(Expr, Expr), | | | recursive without indirection | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Expr` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Expr` representable + | +LL | Plus(Box, Box), + | ^^^^ ^ ^^^^ ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3779.stderr b/src/test/ui/issues/issue-3779.stderr index ba1e842c610ba..9b50ddec12a44 100644 --- a/src/test/ui/issues/issue-3779.stderr +++ b/src/test/ui/issues/issue-3779.stderr @@ -5,9 +5,16 @@ LL | struct S { | ^^^^^^^^ recursive type has infinite size LL | LL | element: Option - | ------------------ recursive without indirection + | --------- recursive without indirection | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `S` representable +help: insert some indirection to make `S` representable + | +LL | element: Box> + | ^^^^ ^ +LL | element: Rc> + | ^^^ ^ +LL | element: &Option + | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-57271.stderr b/src/test/ui/issues/issue-57271.stderr index 4f164624f7a53..a6fe83a9b5636 100644 --- a/src/test/ui/issues/issue-57271.stderr +++ b/src/test/ui/issues/issue-57271.stderr @@ -7,7 +7,14 @@ LL | Class(ClassTypeSignature), LL | Array(TypeSignature), | ------------- recursive without indirection | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ObjectType` representable +help: insert some indirection to make `ObjectType` representable + | +LL | Array(Box), + | ^^^^ ^ +LL | Array(Rc), + | ^^^ ^ +LL | Array(&TypeSignature), + | ^ error[E0072]: recursive type `TypeSignature` has infinite size --> $DIR/issue-57271.rs:19:1 @@ -18,7 +25,14 @@ LL | Base(BaseType), LL | Object(ObjectType), | ---------- recursive without indirection | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `TypeSignature` representable +help: insert some indirection to make `TypeSignature` representable + | +LL | Object(Box), + | ^^^^ ^ +LL | Object(Rc), + | ^^^ ^ +LL | Object(&ObjectType), + | ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/recursion/recursive-enum.stderr b/src/test/ui/recursion/recursive-enum.stderr index e4674b57a6d21..c68badd458bce 100644 --- a/src/test/ui/recursion/recursive-enum.stderr +++ b/src/test/ui/recursion/recursive-enum.stderr @@ -6,7 +6,14 @@ LL | enum List { Cons(T, List), Nil } | | | recursive type has infinite size | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable +help: insert some indirection to make `List` representable + | +LL | enum List { Cons(T, Box>), Nil } + | ^^^^ ^ +LL | enum List { Cons(T, Rc>), Nil } + | ^^^ ^ +LL | enum List { Cons(T, &List), Nil } + | ^ error: aborting due to previous error diff --git a/src/test/ui/sized-cycle-note.stderr b/src/test/ui/sized-cycle-note.stderr index 95bdc34942645..99d8cfd0a05c9 100644 --- a/src/test/ui/sized-cycle-note.stderr +++ b/src/test/ui/sized-cycle-note.stderr @@ -2,21 +2,35 @@ error[E0072]: recursive type `Baz` has infinite size --> $DIR/sized-cycle-note.rs:9:1 | LL | struct Baz { q: Option } - | ^^^^^^^^^^ -------------- recursive without indirection + | ^^^^^^^^^^ ----------- recursive without indirection | | | recursive type has infinite size | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Baz` representable +help: insert some indirection to make `Baz` representable + | +LL | struct Baz { q: Box> } + | ^^^^ ^ +LL | struct Baz { q: Rc> } + | ^^^ ^ +LL | struct Baz { q: &Option } + | ^ error[E0072]: recursive type `Foo` has infinite size --> $DIR/sized-cycle-note.rs:11:1 | LL | struct Foo { q: Option } - | ^^^^^^^^^^ -------------- recursive without indirection + | ^^^^^^^^^^ ----------- recursive without indirection | | | recursive type has infinite size | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable +help: insert some indirection to make `Foo` representable + | +LL | struct Foo { q: Box> } + | ^^^^ ^ +LL | struct Foo { q: Rc> } + | ^^^ ^ +LL | struct Foo { q: &Option } + | ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/span/E0072.stderr b/src/test/ui/span/E0072.stderr index d4a5e7400d2a4..855e4facb7b8c 100644 --- a/src/test/ui/span/E0072.stderr +++ b/src/test/ui/span/E0072.stderr @@ -5,9 +5,16 @@ LL | struct ListNode { | ^^^^^^^^^^^^^^^ recursive type has infinite size LL | head: u8, LL | tail: Option, - | ---------------------- recursive without indirection + | ---------------- recursive without indirection | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable +help: insert some indirection to make `ListNode` representable + | +LL | tail: Box>, + | ^^^^ ^ +LL | tail: Rc>, + | ^^^ ^ +LL | tail: &Option, + | ^ error: aborting due to previous error diff --git a/src/test/ui/span/multiline-span-E0072.stderr b/src/test/ui/span/multiline-span-E0072.stderr index dd322fe833b49..260c2157e96b7 100644 --- a/src/test/ui/span/multiline-span-E0072.stderr +++ b/src/test/ui/span/multiline-span-E0072.stderr @@ -6,11 +6,18 @@ LL | | ListNode LL | | { LL | | head: u8, LL | | tail: Option, - | | ---------------------- recursive without indirection + | | ---------------- recursive without indirection LL | | } | |_^ recursive type has infinite size | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable +help: insert some indirection to make `ListNode` representable + | +LL | tail: Box>, + | ^^^^ ^ +LL | tail: Rc>, + | ^^^ ^ +LL | tail: &Option, + | ^ error: aborting due to previous error diff --git a/src/test/ui/span/recursive-type-field.stderr b/src/test/ui/span/recursive-type-field.stderr index d240872647e50..c1a3270d0a567 100644 --- a/src/test/ui/span/recursive-type-field.stderr +++ b/src/test/ui/span/recursive-type-field.stderr @@ -4,9 +4,16 @@ error[E0072]: recursive type `Foo` has infinite size LL | struct Foo<'a> { | ^^^^^^^^^^^^^^ recursive type has infinite size LL | bar: Bar<'a>, - | ------------ recursive without indirection + | ------- recursive without indirection | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable +help: insert some indirection to make `Foo` representable + | +LL | bar: Box>, + | ^^^^ ^ +LL | bar: Rc>, + | ^^^ ^ +LL | bar: &Bar<'a>, + | ^ error[E0072]: recursive type `Bar` has infinite size --> $DIR/recursive-type-field.rs:8:1 @@ -14,18 +21,18 @@ error[E0072]: recursive type `Bar` has infinite size LL | struct Bar<'a> { | ^^^^^^^^^^^^^^ recursive type has infinite size LL | y: (Foo<'a>, Foo<'a>), - | --------------------- recursive without indirection + | ------------------ recursive without indirection LL | z: Option>, - | ------------------ recursive without indirection + | --------------- recursive without indirection ... LL | d: [Bar<'a>; 1], - | --------------- recursive without indirection + | ------------ recursive without indirection LL | e: Foo<'a>, - | ---------- recursive without indirection + | ------- recursive without indirection LL | x: Bar<'a>, - | ---------- recursive without indirection + | ------- recursive without indirection | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable + = help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable error: aborting due to 2 previous errors diff --git a/src/test/ui/type/type-recursive.stderr b/src/test/ui/type/type-recursive.stderr index 72bf372e561d6..b98a6eac49e04 100644 --- a/src/test/ui/type/type-recursive.stderr +++ b/src/test/ui/type/type-recursive.stderr @@ -5,9 +5,16 @@ LL | struct T1 { | ^^^^^^^^^ recursive type has infinite size LL | foo: isize, LL | foolish: T1 - | ----------- recursive without indirection + | -- recursive without indirection | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `T1` representable +help: insert some indirection to make `T1` representable + | +LL | foolish: Box + | ^^^^ ^ +LL | foolish: Rc + | ^^^ ^ +LL | foolish: &T1 + | ^ error: aborting due to previous error diff --git a/src/test/ui/union/union-nonrepresentable.stderr b/src/test/ui/union/union-nonrepresentable.stderr index 746c1033ea348..70863a549ad25 100644 --- a/src/test/ui/union/union-nonrepresentable.stderr +++ b/src/test/ui/union/union-nonrepresentable.stderr @@ -5,9 +5,16 @@ LL | union U { | ^^^^^^^ recursive type has infinite size LL | a: u8, LL | b: U, - | ---- recursive without indirection + | - recursive without indirection | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `U` representable +help: insert some indirection to make `U` representable + | +LL | b: Box, + | ^^^^ ^ +LL | b: Rc, + | ^^^ ^ +LL | b: &U, + | ^ error: aborting due to previous error From 7cde07e5cc5cfc1665dd64e4c06482c2f10b693a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 30 May 2020 19:58:49 -0700 Subject: [PATCH 21/45] review comments: only suggest one substitution --- .../traits/error_reporting/mod.rs | 49 ++++++------------- .../infinite-tag-type-recursion.stderr | 6 +-- src/test/ui/issues/issue-17431-1.stderr | 6 +-- src/test/ui/issues/issue-17431-2.stderr | 12 +---- src/test/ui/issues/issue-17431-3.stderr | 6 +-- src/test/ui/issues/issue-17431-4.stderr | 6 +-- src/test/ui/issues/issue-17431-5.stderr | 6 +-- src/test/ui/issues/issue-17431-6.stderr | 6 +-- src/test/ui/issues/issue-17431-7.stderr | 6 +-- src/test/ui/issues/issue-2718-a.stderr | 6 +-- src/test/ui/issues/issue-3008-1.stderr | 6 +-- src/test/ui/issues/issue-3008-2.stderr | 6 +-- src/test/ui/issues/issue-3008-3.stderr | 6 +-- src/test/ui/issues/issue-3779.stderr | 6 +-- src/test/ui/issues/issue-57271.stderr | 12 +---- src/test/ui/recursion/recursive-enum.stderr | 6 +-- src/test/ui/sized-cycle-note.stderr | 12 +---- src/test/ui/span/E0072.stderr | 6 +-- src/test/ui/span/multiline-span-E0072.stderr | 6 +-- src/test/ui/span/recursive-type-field.stderr | 6 +-- src/test/ui/type/type-recursive.stderr | 6 +-- .../ui/union/union-nonrepresentable.stderr | 6 +-- 22 files changed, 38 insertions(+), 155 deletions(-) diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index 3457f7b4580c5..d31e04cffd55f 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -1759,48 +1759,27 @@ pub fn recursive_type_with_infinite_size_error( for &span in &spans { err.span_label(span, "recursive without indirection"); } - let short_msg = format!("insert some indirection to make `{}` representable", path); let msg = format!( "insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `{}` representable", path, ); - match &spans[..] { - [span] => { - err.multipart_suggestions( - &short_msg, - vec![ + if spans.len() <= 4 { + err.multipart_suggestion( + &msg, + spans + .iter() + .flat_map(|&span| { vec![ (span.shrink_to_lo(), "Box<".to_string()), (span.shrink_to_hi(), ">".to_string()), - ], - vec![ - (span.shrink_to_lo(), "Rc<".to_string()), - (span.shrink_to_hi(), ">".to_string()), - ], - vec![(span.shrink_to_lo(), "&".to_string())], - ], - Applicability::HasPlaceholders, - ); - } - _ if spans.len() <= 4 => { - err.multipart_suggestion( - &msg, - spans - .iter() - .flat_map(|&span| { - vec![ - (span.shrink_to_lo(), "Box<".to_string()), - (span.shrink_to_hi(), ">".to_string()), - ] - .into_iter() - }) - .collect(), - Applicability::HasPlaceholders, - ); - } - _ => { - err.help(&msg); - } + ] + .into_iter() + }) + .collect(), + Applicability::HasPlaceholders, + ); + } else { + err.help(&msg); } err.emit(); } diff --git a/src/test/ui/infinite/infinite-tag-type-recursion.stderr b/src/test/ui/infinite/infinite-tag-type-recursion.stderr index b6a4d8f4cf563..6d1df4fda2eb0 100644 --- a/src/test/ui/infinite/infinite-tag-type-recursion.stderr +++ b/src/test/ui/infinite/infinite-tag-type-recursion.stderr @@ -6,14 +6,10 @@ LL | enum MList { Cons(isize, MList), Nil } | | | recursive type has infinite size | -help: insert some indirection to make `MList` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `MList` representable | LL | enum MList { Cons(isize, Box), Nil } | ^^^^ ^ -LL | enum MList { Cons(isize, Rc), Nil } - | ^^^ ^ -LL | enum MList { Cons(isize, &MList), Nil } - | ^ error[E0391]: cycle detected when computing drop-check constraints for `MList` --> $DIR/infinite-tag-type-recursion.rs:1:1 diff --git a/src/test/ui/issues/issue-17431-1.stderr b/src/test/ui/issues/issue-17431-1.stderr index 8d44154650e04..58d087ca1998b 100644 --- a/src/test/ui/issues/issue-17431-1.stderr +++ b/src/test/ui/issues/issue-17431-1.stderr @@ -6,14 +6,10 @@ LL | struct Foo { foo: Option> } | | | recursive type has infinite size | -help: insert some indirection to make `Foo` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | LL | struct Foo { foo: Box>> } | ^^^^ ^ -LL | struct Foo { foo: Rc>> } - | ^^^ ^ -LL | struct Foo { foo: &Option> } - | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17431-2.stderr b/src/test/ui/issues/issue-17431-2.stderr index b06184e84da28..eba4bf6d1d5ea 100644 --- a/src/test/ui/issues/issue-17431-2.stderr +++ b/src/test/ui/issues/issue-17431-2.stderr @@ -6,14 +6,10 @@ LL | struct Baz { q: Option } | | | recursive type has infinite size | -help: insert some indirection to make `Baz` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable | LL | struct Baz { q: Box> } | ^^^^ ^ -LL | struct Baz { q: Rc> } - | ^^^ ^ -LL | struct Baz { q: &Option } - | ^ error[E0072]: recursive type `Foo` has infinite size --> $DIR/issue-17431-2.rs:4:1 @@ -23,14 +19,10 @@ LL | struct Foo { q: Option } | | | recursive type has infinite size | -help: insert some indirection to make `Foo` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | LL | struct Foo { q: Box> } | ^^^^ ^ -LL | struct Foo { q: Rc> } - | ^^^ ^ -LL | struct Foo { q: &Option } - | ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-17431-3.stderr b/src/test/ui/issues/issue-17431-3.stderr index f32bd70fd6d94..f6b15d0528ae8 100644 --- a/src/test/ui/issues/issue-17431-3.stderr +++ b/src/test/ui/issues/issue-17431-3.stderr @@ -6,14 +6,10 @@ LL | struct Foo { foo: Mutex> } | | | recursive type has infinite size | -help: insert some indirection to make `Foo` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | LL | struct Foo { foo: Box>> } | ^^^^ ^ -LL | struct Foo { foo: Rc>> } - | ^^^ ^ -LL | struct Foo { foo: &Mutex> } - | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17431-4.stderr b/src/test/ui/issues/issue-17431-4.stderr index 372c5e975c844..aa709e1ad5183 100644 --- a/src/test/ui/issues/issue-17431-4.stderr +++ b/src/test/ui/issues/issue-17431-4.stderr @@ -6,14 +6,10 @@ LL | struct Foo { foo: Option>>, marker: marker::PhantomData | | | recursive type has infinite size | -help: insert some indirection to make `Foo` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | LL | struct Foo { foo: Box>>>, marker: marker::PhantomData } | ^^^^ ^ -LL | struct Foo { foo: Rc>>>, marker: marker::PhantomData } - | ^^^ ^ -LL | struct Foo { foo: &Option>>, marker: marker::PhantomData } - | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17431-5.stderr b/src/test/ui/issues/issue-17431-5.stderr index 01b850ac33694..1558cffb036b3 100644 --- a/src/test/ui/issues/issue-17431-5.stderr +++ b/src/test/ui/issues/issue-17431-5.stderr @@ -6,14 +6,10 @@ LL | struct Bar { x: Bar , marker: marker::PhantomData } | | | recursive type has infinite size | -help: insert some indirection to make `Bar` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable | LL | struct Bar { x: Box> , marker: marker::PhantomData } | ^^^^ ^ -LL | struct Bar { x: Rc> , marker: marker::PhantomData } - | ^^^ ^ -LL | struct Bar { x: &Bar , marker: marker::PhantomData } - | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17431-6.stderr b/src/test/ui/issues/issue-17431-6.stderr index ce6c2db07fb6d..f2aa2a79c8200 100644 --- a/src/test/ui/issues/issue-17431-6.stderr +++ b/src/test/ui/issues/issue-17431-6.stderr @@ -6,14 +6,10 @@ LL | enum Foo { X(Mutex>) } | | | recursive type has infinite size | -help: insert some indirection to make `Foo` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | LL | enum Foo { X(Box>>) } | ^^^^ ^ -LL | enum Foo { X(Rc>>) } - | ^^^ ^ -LL | enum Foo { X(&Mutex>) } - | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17431-7.stderr b/src/test/ui/issues/issue-17431-7.stderr index 4fb563ba502f2..684c3089e85ec 100644 --- a/src/test/ui/issues/issue-17431-7.stderr +++ b/src/test/ui/issues/issue-17431-7.stderr @@ -6,14 +6,10 @@ LL | enum Foo { Voo(Option>) } | | | recursive type has infinite size | -help: insert some indirection to make `Foo` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | LL | enum Foo { Voo(Box>>) } | ^^^^ ^ -LL | enum Foo { Voo(Rc>>) } - | ^^^ ^ -LL | enum Foo { Voo(&Option>) } - | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-2718-a.stderr b/src/test/ui/issues/issue-2718-a.stderr index 48b7a61e059ea..d152ffde4e57d 100644 --- a/src/test/ui/issues/issue-2718-a.stderr +++ b/src/test/ui/issues/issue-2718-a.stderr @@ -7,14 +7,10 @@ LL | pub struct Pong(SendPacket); | | recursive without indirection | recursive type has infinite size | -help: insert some indirection to make `pingpong::Pong` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `pingpong::Pong` representable | LL | pub struct Pong(Box>); | ^^^^ ^ -LL | pub struct Pong(Rc>); - | ^^^ ^ -LL | pub struct Pong(&SendPacket); - | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3008-1.stderr b/src/test/ui/issues/issue-3008-1.stderr index d1173a4b3334c..87ee36df21696 100644 --- a/src/test/ui/issues/issue-3008-1.stderr +++ b/src/test/ui/issues/issue-3008-1.stderr @@ -7,14 +7,10 @@ LL | enum Bar { LL | BarSome(Bar) | --- recursive without indirection | -help: insert some indirection to make `Bar` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable | LL | BarSome(Box) | ^^^^ ^ -LL | BarSome(Rc) - | ^^^ ^ -LL | BarSome(&Bar) - | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3008-2.stderr b/src/test/ui/issues/issue-3008-2.stderr index 4fd60639b21a8..369a19d37e6f6 100644 --- a/src/test/ui/issues/issue-3008-2.stderr +++ b/src/test/ui/issues/issue-3008-2.stderr @@ -6,14 +6,10 @@ LL | struct Bar { x: Bar } | | | recursive type has infinite size | -help: insert some indirection to make `Bar` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable | LL | struct Bar { x: Box } | ^^^^ ^ -LL | struct Bar { x: Rc } - | ^^^ ^ -LL | struct Bar { x: &Bar } - | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3008-3.stderr b/src/test/ui/issues/issue-3008-3.stderr index e6efad9188300..0b162eff94a7c 100644 --- a/src/test/ui/issues/issue-3008-3.stderr +++ b/src/test/ui/issues/issue-3008-3.stderr @@ -6,14 +6,10 @@ LL | enum E2 { V2(E2, marker::PhantomData), } | | | recursive type has infinite size | -help: insert some indirection to make `E2` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `E2` representable | LL | enum E2 { V2(Box>, marker::PhantomData), } | ^^^^ ^ -LL | enum E2 { V2(Rc>, marker::PhantomData), } - | ^^^ ^ -LL | enum E2 { V2(&E2, marker::PhantomData), } - | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3779.stderr b/src/test/ui/issues/issue-3779.stderr index 9b50ddec12a44..7b17e91421660 100644 --- a/src/test/ui/issues/issue-3779.stderr +++ b/src/test/ui/issues/issue-3779.stderr @@ -7,14 +7,10 @@ LL | LL | element: Option | --------- recursive without indirection | -help: insert some indirection to make `S` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `S` representable | LL | element: Box> | ^^^^ ^ -LL | element: Rc> - | ^^^ ^ -LL | element: &Option - | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-57271.stderr b/src/test/ui/issues/issue-57271.stderr index a6fe83a9b5636..b7c799e163cee 100644 --- a/src/test/ui/issues/issue-57271.stderr +++ b/src/test/ui/issues/issue-57271.stderr @@ -7,14 +7,10 @@ LL | Class(ClassTypeSignature), LL | Array(TypeSignature), | ------------- recursive without indirection | -help: insert some indirection to make `ObjectType` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ObjectType` representable | LL | Array(Box), | ^^^^ ^ -LL | Array(Rc), - | ^^^ ^ -LL | Array(&TypeSignature), - | ^ error[E0072]: recursive type `TypeSignature` has infinite size --> $DIR/issue-57271.rs:19:1 @@ -25,14 +21,10 @@ LL | Base(BaseType), LL | Object(ObjectType), | ---------- recursive without indirection | -help: insert some indirection to make `TypeSignature` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `TypeSignature` representable | LL | Object(Box), | ^^^^ ^ -LL | Object(Rc), - | ^^^ ^ -LL | Object(&ObjectType), - | ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/recursion/recursive-enum.stderr b/src/test/ui/recursion/recursive-enum.stderr index c68badd458bce..ab4709d8e709e 100644 --- a/src/test/ui/recursion/recursive-enum.stderr +++ b/src/test/ui/recursion/recursive-enum.stderr @@ -6,14 +6,10 @@ LL | enum List { Cons(T, List), Nil } | | | recursive type has infinite size | -help: insert some indirection to make `List` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `List` representable | LL | enum List { Cons(T, Box>), Nil } | ^^^^ ^ -LL | enum List { Cons(T, Rc>), Nil } - | ^^^ ^ -LL | enum List { Cons(T, &List), Nil } - | ^ error: aborting due to previous error diff --git a/src/test/ui/sized-cycle-note.stderr b/src/test/ui/sized-cycle-note.stderr index 99d8cfd0a05c9..45062c2ea6c72 100644 --- a/src/test/ui/sized-cycle-note.stderr +++ b/src/test/ui/sized-cycle-note.stderr @@ -6,14 +6,10 @@ LL | struct Baz { q: Option } | | | recursive type has infinite size | -help: insert some indirection to make `Baz` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable | LL | struct Baz { q: Box> } | ^^^^ ^ -LL | struct Baz { q: Rc> } - | ^^^ ^ -LL | struct Baz { q: &Option } - | ^ error[E0072]: recursive type `Foo` has infinite size --> $DIR/sized-cycle-note.rs:11:1 @@ -23,14 +19,10 @@ LL | struct Foo { q: Option } | | | recursive type has infinite size | -help: insert some indirection to make `Foo` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | LL | struct Foo { q: Box> } | ^^^^ ^ -LL | struct Foo { q: Rc> } - | ^^^ ^ -LL | struct Foo { q: &Option } - | ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/span/E0072.stderr b/src/test/ui/span/E0072.stderr index 855e4facb7b8c..06493f05142e6 100644 --- a/src/test/ui/span/E0072.stderr +++ b/src/test/ui/span/E0072.stderr @@ -7,14 +7,10 @@ LL | head: u8, LL | tail: Option, | ---------------- recursive without indirection | -help: insert some indirection to make `ListNode` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable | LL | tail: Box>, | ^^^^ ^ -LL | tail: Rc>, - | ^^^ ^ -LL | tail: &Option, - | ^ error: aborting due to previous error diff --git a/src/test/ui/span/multiline-span-E0072.stderr b/src/test/ui/span/multiline-span-E0072.stderr index 260c2157e96b7..55128347f7404 100644 --- a/src/test/ui/span/multiline-span-E0072.stderr +++ b/src/test/ui/span/multiline-span-E0072.stderr @@ -10,14 +10,10 @@ LL | | tail: Option, LL | | } | |_^ recursive type has infinite size | -help: insert some indirection to make `ListNode` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable | LL | tail: Box>, | ^^^^ ^ -LL | tail: Rc>, - | ^^^ ^ -LL | tail: &Option, - | ^ error: aborting due to previous error diff --git a/src/test/ui/span/recursive-type-field.stderr b/src/test/ui/span/recursive-type-field.stderr index c1a3270d0a567..fb1d98b58dfbe 100644 --- a/src/test/ui/span/recursive-type-field.stderr +++ b/src/test/ui/span/recursive-type-field.stderr @@ -6,14 +6,10 @@ LL | struct Foo<'a> { LL | bar: Bar<'a>, | ------- recursive without indirection | -help: insert some indirection to make `Foo` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | LL | bar: Box>, | ^^^^ ^ -LL | bar: Rc>, - | ^^^ ^ -LL | bar: &Bar<'a>, - | ^ error[E0072]: recursive type `Bar` has infinite size --> $DIR/recursive-type-field.rs:8:1 diff --git a/src/test/ui/type/type-recursive.stderr b/src/test/ui/type/type-recursive.stderr index b98a6eac49e04..d6d32cc5d6f39 100644 --- a/src/test/ui/type/type-recursive.stderr +++ b/src/test/ui/type/type-recursive.stderr @@ -7,14 +7,10 @@ LL | foo: isize, LL | foolish: T1 | -- recursive without indirection | -help: insert some indirection to make `T1` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T1` representable | LL | foolish: Box | ^^^^ ^ -LL | foolish: Rc - | ^^^ ^ -LL | foolish: &T1 - | ^ error: aborting due to previous error diff --git a/src/test/ui/union/union-nonrepresentable.stderr b/src/test/ui/union/union-nonrepresentable.stderr index 70863a549ad25..c54d04de12c50 100644 --- a/src/test/ui/union/union-nonrepresentable.stderr +++ b/src/test/ui/union/union-nonrepresentable.stderr @@ -7,14 +7,10 @@ LL | a: u8, LL | b: U, | - recursive without indirection | -help: insert some indirection to make `U` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `U` representable | LL | b: Box, | ^^^^ ^ -LL | b: Rc, - | ^^^ ^ -LL | b: &U, - | ^ error: aborting due to previous error From 03552ec3fa4828329874a17d1b8966a0c03809d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 10 Jun 2020 14:54:27 -0700 Subject: [PATCH 22/45] fix rebase --- src/test/ui/issues/issue-72554.stderr | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/ui/issues/issue-72554.stderr b/src/test/ui/issues/issue-72554.stderr index 9db65f4a2ee8f..9de94c393a711 100644 --- a/src/test/ui/issues/issue-72554.stderr +++ b/src/test/ui/issues/issue-72554.stderr @@ -6,7 +6,10 @@ LL | pub enum ElemDerived { LL | A(ElemDerived) | ----------- recursive without indirection | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ElemDerived` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ElemDerived` representable + | +LL | A(Box) + | ^^^^ ^ error: aborting due to previous error From 7f3bb398fa90d68c737dd7e00a3813e0620ba472 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Wed, 10 Jun 2020 23:13:45 +0200 Subject: [PATCH 23/45] Add a TryFrom> impl that mirror from_vec_with_nul --- src/libstd/ffi/c_str.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 6f7dc091897f4..3a3b51fd353b2 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -1,6 +1,7 @@ use crate::ascii; use crate::borrow::{Borrow, Cow}; use crate::cmp::Ordering; +use crate::convert::TryFrom; use crate::error::Error; use crate::fmt::{self, Write}; use crate::io; @@ -853,6 +854,19 @@ impl From> for CString { } } +#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] +impl TryFrom> for CString { + type Error = FromBytesWithNulError; + + /// See the document about [`from_vec_with_nul`] for more + /// informations about the behaviour of this method. + /// + /// [`from_vec_with_nul`]: struct.CString.html#method.from_vec_with_nul + fn try_from(value: Vec) -> Result { + Self::from_vec_with_nul(value) + } +} + #[stable(feature = "more_box_slice_clone", since = "1.29.0")] impl Clone for Box { #[inline] From 6b955268d71907d9049a399a0e0a33f6448e1221 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Thu, 11 Jun 2020 16:55:03 +0200 Subject: [PATCH 24/45] Fix the link in the TryFrom impl --- src/libstd/ffi/c_str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 3a3b51fd353b2..298f6c33457d8 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -861,7 +861,7 @@ impl TryFrom> for CString { /// See the document about [`from_vec_with_nul`] for more /// informations about the behaviour of this method. /// - /// [`from_vec_with_nul`]: struct.CString.html#method.from_vec_with_nul + /// [`from_vec_with_nul`]: CString::from_vec_with_nul fn try_from(value: Vec) -> Result { Self::from_vec_with_nul(value) } From c0aef6d816aa1f4a94e1057788e131ba82384d36 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 12 Jun 2020 14:17:42 -0700 Subject: [PATCH 25/45] Remove vestigial CI job msvc-aux. --- .github/workflows/ci.yml | 5 ----- src/bootstrap/builder.rs | 1 - src/bootstrap/mk/Makefile.in | 10 ++-------- src/bootstrap/test.rs | 7 ------- src/ci/azure-pipelines/auto.yml | 4 ---- src/ci/github-actions/ci.yml | 6 ------ 6 files changed, 2 insertions(+), 31 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3c95226aebf6..72329a3572798 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -434,11 +434,6 @@ jobs: NO_DEBUG_ASSERTIONS: 1 NO_LLVM_ASSERTIONS: 1 os: windows-latest-xl - - name: x86_64-msvc-aux - env: - RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 - RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc" - os: windows-latest-xl - name: x86_64-msvc-cargo env: SCRIPT: python x.py test src/tools/cargotest src/tools/cargo diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index ffdd8485181f4..64e84da795a33 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -371,7 +371,6 @@ impl<'a> Builder<'a> { test::UiFullDeps, test::Rustdoc, test::Pretty, - test::RunPassValgrindPretty, test::Crate, test::CrateLibrustc, test::CrateRustdoc, diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index d8c97fc741478..12a1734e21c7e 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -6,12 +6,6 @@ Q := @ BOOTSTRAP_ARGS := endif -ifdef EXCLUDE_CARGO -AUX_ARGS := -else -AUX_ARGS := src/tools/cargo src/tools/cargotest -endif - BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py all: @@ -48,8 +42,8 @@ check: $(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS) check-aux: $(Q)$(BOOTSTRAP) test \ - src/test/run-pass-valgrind/pretty \ - $(AUX_ARGS) \ + src/tools/cargo \ + src/tools/cargotest \ $(BOOTSTRAP_ARGS) check-bootstrap: $(Q)$(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap_test.py diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 163132f563425..fb30ec0ffa49e 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -929,13 +929,6 @@ host_test!(UiFullDeps { path: "src/test/ui-fulldeps", mode: "ui", suite: "ui-ful host_test!(Rustdoc { path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" }); host_test!(Pretty { path: "src/test/pretty", mode: "pretty", suite: "pretty" }); -test!(RunPassValgrindPretty { - path: "src/test/run-pass-valgrind/pretty", - mode: "pretty", - suite: "run-pass-valgrind", - default: false, - host: true -}); default_test!(RunMake { path: "src/test/run-make", mode: "run-make", suite: "run-make" }); diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml index f8fa7b727d179..3de27bc54c5c0 100644 --- a/src/ci/azure-pipelines/auto.yml +++ b/src/ci/azure-pipelines/auto.yml @@ -142,10 +142,6 @@ jobs: # FIXME(#59637) NO_DEBUG_ASSERTIONS: 1 NO_LLVM_ASSERTIONS: 1 - # MSVC aux tests - x86_64-msvc-aux: - RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 - INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc x86_64-msvc-cargo: SCRIPT: python x.py test src/tools/cargotest src/tools/cargo INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 92fec593a5410..3150ebd75a66e 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -496,12 +496,6 @@ jobs: NO_LLVM_ASSERTIONS: 1 <<: *job-windows-xl - - name: x86_64-msvc-aux - env: - RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc - <<: *job-windows-xl - - name: x86_64-msvc-cargo env: SCRIPT: python x.py test src/tools/cargotest src/tools/cargo From 8b2092803e71180cd352f42041bf1725dc4ad1f6 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sat, 13 Jun 2020 01:27:14 +0000 Subject: [PATCH 26/45] Stabilize Option::zip --- src/libcore/lib.rs | 1 - src/libcore/option.rs | 8 +++++--- src/librustc_trait_selection/lib.rs | 1 - .../clippy_lints/src/checked_conversions.rs | 15 +++++---------- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 7d21f9a9a66d0..fe05e914e6d44 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -145,7 +145,6 @@ #![feature(associated_type_bounds)] #![feature(const_type_id)] #![feature(const_caller_location)] -#![feature(option_zip)] #![feature(no_niche)] // rust-lang/rust#68303 #[prelude_import] diff --git a/src/libcore/option.rs b/src/libcore/option.rs index e8483875c97e5..5f0a12678ff43 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -926,7 +926,6 @@ impl Option { /// # Examples /// /// ``` - /// #![feature(option_zip)] /// let x = Some(1); /// let y = Some("hi"); /// let z = None::; @@ -934,9 +933,12 @@ impl Option { /// assert_eq!(x.zip(y), Some((1, "hi"))); /// assert_eq!(x.zip(z), None); /// ``` - #[unstable(feature = "option_zip", issue = "70086")] + #[stable(feature = "option_zip_option", since = "1.46.0")] pub fn zip(self, other: Option) -> Option<(T, U)> { - self.zip_with(other, |a, b| (a, b)) + match (self, other) { + (Some(a), Some(b)) => Some((a, b)), + _ => None, + } } /// Zips `self` and another `Option` with function `f`. diff --git a/src/librustc_trait_selection/lib.rs b/src/librustc_trait_selection/lib.rs index 044239b047a4e..ea886cd1f9e9b 100644 --- a/src/librustc_trait_selection/lib.rs +++ b/src/librustc_trait_selection/lib.rs @@ -16,7 +16,6 @@ #![feature(in_band_lifetimes)] #![feature(crate_visibility_modifier)] #![feature(or_patterns)] -#![feature(option_zip)] #![recursion_limit = "512"] // For rustdoc #[macro_use] diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs index e845ef99c7cc0..88145015ba8bd 100644 --- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs @@ -88,7 +88,7 @@ fn double_check<'a>(cx: &LateContext<'_, '_>, left: &'a Expr<'_>, right: &'a Exp let upper = check_upper_bound(l); let lower = check_lower_bound(r); - transpose(upper, lower).and_then(|(l, r)| l.combine(r, cx)) + upper.zip(lower).and_then(|(l, r)| l.combine(r, cx)) }; upper_lower(left, right).or_else(|| upper_lower(right, left)) @@ -131,7 +131,10 @@ impl<'a> Conversion<'a> { /// Checks if the to-type is the same (if there is a type constraint) fn has_compatible_to_type(&self, other: &Self) -> bool { - transpose(self.to_type.as_ref(), other.to_type.as_ref()).map_or(true, |(l, r)| l == r) + match (self.to_type, other.to_type) { + (Some(l), Some(r)) => l == r, + _ => true, + } } /// Try to construct a new conversion if the conversion type is valid @@ -322,14 +325,6 @@ fn int_ty_to_sym<'tcx>(path: &QPath<'_>) -> Option<&'tcx str> { } } -/// (Option, Option) -> Option<(T, U)> -fn transpose(lhs: Option, rhs: Option) -> Option<(T, U)> { - match (lhs, rhs) { - (Some(l), Some(r)) => Some((l, r)), - _ => None, - } -} - /// Will return the expressions as if they were expr1 <= expr2 fn normalize_le_ge<'a>(op: &BinOp, left: &'a Expr<'a>, right: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> { match op.node { From c45231ca555950cea450ba65f9d2d1962e3af6cd Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 12 Jun 2020 22:12:45 -0700 Subject: [PATCH 27/45] Revert heterogeneous SocketAddr PartialEq impls These lead to inference regressions (mostly in tests) in code that looks like: let socket = std::net::SocketAddrV4::new(std::net::Ipv4Addr::new(127, 0, 0, 1), 8080); assert_eq!(socket, "127.0.0.1:8080".parse().unwrap()); That compiles as of stable 1.44.0 but fails in beta with: error[E0284]: type annotations needed --> src/main.rs:3:41 | 3 | assert_eq!(socket, "127.0.0.1:8080".parse().unwrap()); | ^^^^^ cannot infer type for type parameter `F` declared on the associated function `parse` | = note: cannot satisfy `<_ as std::str::FromStr>::Err == _` help: consider specifying the type argument in the method call | 3 | assert_eq!(socket, "127.0.0.1:8080".parse::().unwrap()); | --- src/libstd/net/addr.rs | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index b780340884e1f..7e3c3e8f3042e 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -694,42 +694,6 @@ impl PartialEq for SocketAddrV6 { && self.inner.sin6_scope_id == other.inner.sin6_scope_id } } -#[stable(feature = "socketaddr_ordering", since = "1.45.0")] -impl PartialEq for SocketAddr { - fn eq(&self, other: &SocketAddrV4) -> bool { - match self { - SocketAddr::V4(v4) => v4 == other, - SocketAddr::V6(_) => false, - } - } -} -#[stable(feature = "socketaddr_ordering", since = "1.45.0")] -impl PartialEq for SocketAddr { - fn eq(&self, other: &SocketAddrV6) -> bool { - match self { - SocketAddr::V4(_) => false, - SocketAddr::V6(v6) => v6 == other, - } - } -} -#[stable(feature = "socketaddr_ordering", since = "1.45.0")] -impl PartialEq for SocketAddrV4 { - fn eq(&self, other: &SocketAddr) -> bool { - match other { - SocketAddr::V4(v4) => self == v4, - SocketAddr::V6(_) => false, - } - } -} -#[stable(feature = "socketaddr_ordering", since = "1.45.0")] -impl PartialEq for SocketAddrV6 { - fn eq(&self, other: &SocketAddr) -> bool { - match other { - SocketAddr::V4(_) => false, - SocketAddr::V6(v6) => self == v6, - } - } -} #[stable(feature = "rust1", since = "1.0.0")] impl Eq for SocketAddrV4 {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1242,12 +1206,8 @@ mod tests { // equality assert_eq!(v4_1, v4_1); assert_eq!(v6_1, v6_1); - assert_eq!(v4_1, SocketAddr::V4(v4_1)); - assert_eq!(v6_1, SocketAddr::V6(v6_1)); assert_eq!(SocketAddr::V4(v4_1), SocketAddr::V4(v4_1)); assert_eq!(SocketAddr::V6(v6_1), SocketAddr::V6(v6_1)); - assert!(v4_1 != SocketAddr::V6(v6_1)); - assert!(v6_1 != SocketAddr::V4(v4_1)); assert!(v4_1 != v4_2); assert!(v6_1 != v6_2); From f747073fc1751afd2cfd4395283a4822b618f2da Mon Sep 17 00:00:00 2001 From: Poliorcetics Date: Sat, 13 Jun 2020 18:41:01 +0200 Subject: [PATCH 28/45] Apply suggestions from code review Co-authored-by: David Tolnay --- src/libstd/sync/mutex.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index b3ef521d6ecb0..6625d4659dcac 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -108,8 +108,8 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// *guard += 1; /// ``` /// -/// It is sometimes a good idea (or even necessary) to manually drop the mutex -/// to unlock it as soon as possible. If you need the resource until the end of +/// It is sometimes necessary to manually drop the mutex +/// guard to unlock it as soon as possible. If you need the resource until the end of /// the scope, this is not needed. /// /// ``` @@ -140,16 +140,16 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// // This is the result of some important and long-ish work. /// let result = data.iter().fold(0, |acc, x| acc + x * 2); /// data.push(result); -/// // We drop the `data` explicitely because it's not necessary anymore +/// // We drop the `data` explicitly because it's not necessary anymore /// // and the thread still has work to do. This allow other threads to /// // start working on the data immediately, without waiting /// // for the rest of the unrelated work to be done here. /// // /// // It's even more important here than in the threads because we `.join` the -/// // threads after that. If we had not dropped the lock, a thread could be +/// // threads after that. If we had not dropped the mutex guard, a thread could be /// // waiting forever for it, causing a deadlock. /// drop(data); -/// // Here the lock is not assigned to a variable and so, even if the scope +/// // Here the mutex guard is not assigned to a variable and so, even if the scope /// // does not end after this line, the mutex is still released: /// // there is no deadlock. /// *res_mutex.lock().unwrap() += result; From 34b3ff06e101f60cb69268ee83c93c177b63c322 Mon Sep 17 00:00:00 2001 From: Poliorcetics Date: Sat, 13 Jun 2020 18:43:37 +0200 Subject: [PATCH 29/45] Clarify the scope-related explanation Based on the review made by dtolnay. --- src/libstd/sync/mutex.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 6625d4659dcac..37c8125b0984a 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -108,9 +108,8 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// *guard += 1; /// ``` /// -/// It is sometimes necessary to manually drop the mutex -/// guard to unlock it as soon as possible. If you need the resource until the end of -/// the scope, this is not needed. +/// It is sometimes necessary to manually drop the mutex guard +/// to unlock it sooner than the end of the enclosing scope. /// /// ``` /// use std::sync::{Arc, Mutex}; From c010e711ca5ec02012afb83c0d99aec9d26a9eea Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 13 Jun 2020 10:11:02 -0700 Subject: [PATCH 30/45] Rewrap comments in Mutex example --- src/libstd/sync/mutex.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 37c8125b0984a..8478457eabfc2 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -108,8 +108,8 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// *guard += 1; /// ``` /// -/// It is sometimes necessary to manually drop the mutex guard -/// to unlock it sooner than the end of the enclosing scope. +/// It is sometimes necessary to manually drop the mutex guard to unlock it +/// sooner than the end of the enclosing scope. /// /// ``` /// use std::sync::{Arc, Mutex}; @@ -139,18 +139,18 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// // This is the result of some important and long-ish work. /// let result = data.iter().fold(0, |acc, x| acc + x * 2); /// data.push(result); -/// // We drop the `data` explicitly because it's not necessary anymore -/// // and the thread still has work to do. This allow other threads to -/// // start working on the data immediately, without waiting -/// // for the rest of the unrelated work to be done here. +/// // We drop the `data` explicitly because it's not necessary anymore and the +/// // thread still has work to do. This allow other threads to start working on +/// // the data immediately, without waiting for the rest of the unrelated work +/// // to be done here. /// // /// // It's even more important here than in the threads because we `.join` the -/// // threads after that. If we had not dropped the mutex guard, a thread could be -/// // waiting forever for it, causing a deadlock. +/// // threads after that. If we had not dropped the mutex guard, a thread could +/// // be waiting forever for it, causing a deadlock. /// drop(data); -/// // Here the mutex guard is not assigned to a variable and so, even if the scope -/// // does not end after this line, the mutex is still released: -/// // there is no deadlock. +/// // Here the mutex guard is not assigned to a variable and so, even if the +/// // scope does not end after this line, the mutex is still released: there is +/// // no deadlock. /// *res_mutex.lock().unwrap() += result; /// /// threads.into_iter().for_each(|thread| { From 204c236ad5b632294d8794e729326be8053ab2aa Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 13 Jun 2020 10:21:11 -0700 Subject: [PATCH 31/45] Add test for comparing SocketAddr with inferred right-hand side --- src/libstd/net/addr.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index 7e3c3e8f3042e..b8fa1a7f744d3 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -1228,5 +1228,10 @@ mod tests { assert!(v6_1 < v6_3); assert!(v4_3 > v4_1); assert!(v6_3 > v6_1); + + // compare with an inferred right-hand side + assert_eq!(v4_1, "224.120.45.1:23456".parse().unwrap()); + assert_eq!(v6_1, "[2001:db8:f00::1002]:23456".parse().unwrap()); + assert_eq!(SocketAddr::V4(v4_1), "224.120.45.1:23456".parse().unwrap()); } } From 71d41d9e9f020c9eb527a47e16e4041dfcdaef84 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sat, 13 Jun 2020 20:51:00 +0200 Subject: [PATCH 32/45] add TcpListener support for HermitCore Add basic support of TcpListerner for HermitCore. In addition, revise TcpStream to support peer_addr. --- src/libstd/sys/hermit/net.rs | 157 +++++++++++++++++++++++++---------- 1 file changed, 111 insertions(+), 46 deletions(-) diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs index 5b5379c8b0581..2fef8d381ca1a 100644 --- a/src/libstd/sys/hermit/net.rs +++ b/src/libstd/sys/hermit/net.rs @@ -1,10 +1,13 @@ use crate::convert::TryFrom; use crate::fmt; use crate::io::{self, ErrorKind, IoSlice, IoSliceMut}; -use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; +use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::str; +use crate::sync::Arc; use crate::sys::hermit::abi; +use crate::sys::hermit::abi::IpAddress::{Ipv4, Ipv6}; use crate::sys::{unsupported, Void}; +use crate::sys_common::AsInner; use crate::time::Duration; /// Checks whether the HermitCore's socket interface has been started already, and @@ -17,14 +20,37 @@ pub fn init() -> io::Result<()> { Ok(()) } -pub struct TcpStream(abi::Handle); +#[derive(Debug, Clone)] +pub struct Socket(abi::Handle); + +impl Socket { + fn new(handle: abi::Handle) -> Socket { + Socket(handle) + } +} + +impl AsInner for Socket { + fn as_inner(&self) -> &abi::Handle { + &self.0 + } +} + +impl Drop for Socket { + fn drop(&mut self) { + let _ = abi::tcpstream::close(self.0); + } +} + + +#[derive(Clone)] +pub struct TcpStream(Arc); impl TcpStream { pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result { let addr = addr?; match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) { - Ok(handle) => Ok(TcpStream(handle)), + Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))), _ => { Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket")) } @@ -37,7 +63,7 @@ impl TcpStream { saddr.port(), Some(duration.as_millis() as u64), ) { - Ok(handle) => Ok(TcpStream(handle)), + Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))), _ => { Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket")) } @@ -45,31 +71,34 @@ impl TcpStream { } pub fn set_read_timeout(&self, duration: Option) -> io::Result<()> { - abi::tcpstream::set_read_timeout(self.0, duration.map(|d| d.as_millis() as u64)) + abi::tcpstream::set_read_timeout(*self.0.as_inner(), duration.map(|d| d.as_millis() as u64)) .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value")) } pub fn set_write_timeout(&self, duration: Option) -> io::Result<()> { - abi::tcpstream::set_write_timeout(self.0, duration.map(|d| d.as_millis() as u64)) - .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value")) + abi::tcpstream::set_write_timeout( + *self.0.as_inner(), + duration.map(|d| d.as_millis() as u64), + ) + .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value")) } pub fn read_timeout(&self) -> io::Result> { - let duration = abi::tcpstream::get_read_timeout(self.0) + let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner()) .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?; Ok(duration.map(|d| Duration::from_millis(d))) } pub fn write_timeout(&self) -> io::Result> { - let duration = abi::tcpstream::get_write_timeout(self.0) + let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner()) .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?; Ok(duration.map(|d| Duration::from_millis(d))) } pub fn peek(&self, buf: &mut [u8]) -> io::Result { - abi::tcpstream::peek(self.0, buf) + abi::tcpstream::peek(*self.0.as_inner(), buf) .map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed")) } @@ -81,18 +110,11 @@ impl TcpStream { let mut size: usize = 0; for i in ioslice.iter_mut() { - let mut pos: usize = 0; - - while pos < i.len() { - let ret = abi::tcpstream::read(self.0, &mut i[pos..]) - .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to read on socket"))?; - - if ret == 0 { - return Ok(size); - } else { - size += ret; - pos += ret; - } + let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..]) + .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to read on socket"))?; + + if ret != 0 { + size += ret; } } @@ -112,7 +134,7 @@ impl TcpStream { let mut size: usize = 0; for i in ioslice.iter() { - size += abi::tcpstream::write(self.0, i) + size += abi::tcpstream::write(*self.0.as_inner(), i) .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to write on socket"))?; } @@ -125,7 +147,32 @@ impl TcpStream { } pub fn peer_addr(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "peer_addr isn't supported")) + let (ipaddr, port) = abi::tcpstream::peer_addr(*self.0.as_inner()) + .map_err(|_| io::Error::new(ErrorKind::Other, "peer_addr failed"))?; + + let saddr = match ipaddr { + Ipv4(ref addr) => SocketAddr::new( + IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])), + port, + ), + Ipv6(ref addr) => SocketAddr::new( + IpAddr::V6(Ipv6Addr::new( + ((addr.0[0] as u16) << 8) | addr.0[1] as u16, + ((addr.0[2] as u16) << 8) | addr.0[3] as u16, + ((addr.0[4] as u16) << 8) | addr.0[5] as u16, + ((addr.0[6] as u16) << 8) | addr.0[7] as u16, + ((addr.0[8] as u16) << 8) | addr.0[9] as u16, + ((addr.0[10] as u16) << 8) | addr.0[11] as u16, + ((addr.0[12] as u16) << 8) | addr.0[13] as u16, + ((addr.0[14] as u16) << 8) | addr.0[15] as u16)), + port, + ), + _ => { + return Err(io::Error::new(ErrorKind::Other, "peer_addr failed")); + }, + }; + + Ok(saddr) } pub fn socket_addr(&self) -> io::Result { @@ -133,34 +180,31 @@ impl TcpStream { } pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { - abi::tcpstream::shutdown(self.0, how as i32) + abi::tcpstream::shutdown(*self.0.as_inner(), how as i32) .map_err(|_| io::Error::new(ErrorKind::Other, "unable to shutdown socket")) } pub fn duplicate(&self) -> io::Result { - let handle = abi::tcpstream::duplicate(self.0) - .map_err(|_| io::Error::new(ErrorKind::Other, "unable to duplicate stream"))?; - - Ok(TcpStream(handle)) + Ok(self.clone()) } pub fn set_nodelay(&self, mode: bool) -> io::Result<()> { - abi::tcpstream::set_nodelay(self.0, mode) + abi::tcpstream::set_nodelay(*self.0.as_inner(), mode) .map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed")) } pub fn nodelay(&self) -> io::Result { - abi::tcpstream::nodelay(self.0) + abi::tcpstream::nodelay(*self.0.as_inner()) .map_err(|_| io::Error::new(ErrorKind::Other, "nodelay failed")) } pub fn set_ttl(&self, tll: u32) -> io::Result<()> { - abi::tcpstream::set_tll(self.0, tll) + abi::tcpstream::set_tll(*self.0.as_inner(), tll) .map_err(|_| io::Error::new(ErrorKind::Other, "unable to set TTL")) } pub fn ttl(&self) -> io::Result { - abi::tcpstream::get_tll(self.0) + abi::tcpstream::get_tll(*self.0.as_inner()) .map_err(|_| io::Error::new(ErrorKind::Other, "unable to get TTL")) } @@ -169,40 +213,61 @@ impl TcpStream { } pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> { - abi::tcpstream::set_nonblocking(self.0, mode) + abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode) .map_err(|_| io::Error::new(ErrorKind::Other, "unable to set blocking mode")) } } -impl Drop for TcpStream { - fn drop(&mut self) { - let _ = abi::tcpstream::close(self.0); - } -} - impl fmt::Debug for TcpStream { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { Ok(()) } } -pub struct TcpListener(abi::Handle); +#[derive(Clone)] +pub struct TcpListener(SocketAddr); impl TcpListener { - pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result { + let addr = addr?; + + Ok(TcpListener(*addr)) } pub fn socket_addr(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Ok(self.0) } pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + let (handle, ipaddr, port) = abi::tcplistener::accept(self.0.port()) + .map_err(|_| io::Error::new(ErrorKind::Other, "accept failed"))?; + let saddr = match ipaddr { + Ipv4(ref addr) => SocketAddr::new( + IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])), + port, + ), + Ipv6(ref addr) => SocketAddr::new( + IpAddr::V6(Ipv6Addr::new( + ((addr.0[0] as u16) << 8) | addr.0[1] as u16, + ((addr.0[2] as u16) << 8) | addr.0[3] as u16, + ((addr.0[4] as u16) << 8) | addr.0[5] as u16, + ((addr.0[6] as u16) << 8) | addr.0[7] as u16, + ((addr.0[8] as u16) << 8) | addr.0[9] as u16, + ((addr.0[10] as u16) << 8) | addr.0[11] as u16, + ((addr.0[12] as u16) << 8) | addr.0[13] as u16, + ((addr.0[14] as u16) << 8) | addr.0[15] as u16)), + port, + ), + _ => { + return Err(io::Error::new(ErrorKind::Other, "accept failed")); + }, + }; + + Ok((TcpStream(Arc::new(Socket(handle))), saddr)) } pub fn duplicate(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Ok(self.clone()) } pub fn set_ttl(&self, _: u32) -> io::Result<()> { From c99116afe37d5a1dde65ed8a2e107892be81b20a Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 14 Jun 2020 00:38:31 +0200 Subject: [PATCH 33/45] remove unused function --- src/libstd/sys/hermit/net.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs index 2fef8d381ca1a..70c010e6232f8 100644 --- a/src/libstd/sys/hermit/net.rs +++ b/src/libstd/sys/hermit/net.rs @@ -23,12 +23,6 @@ pub fn init() -> io::Result<()> { #[derive(Debug, Clone)] pub struct Socket(abi::Handle); -impl Socket { - fn new(handle: abi::Handle) -> Socket { - Socket(handle) - } -} - impl AsInner for Socket { fn as_inner(&self) -> &abi::Handle { &self.0 From fd86a847206dd2333c23c768b8c0564e15a05c1c Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 14 Jun 2020 00:39:14 +0200 Subject: [PATCH 34/45] use latest interface to HermitCore --- Cargo.lock | 4 ++-- src/libstd/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bbbcf797f7535..009767934d447 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1434,9 +1434,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" +checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909" dependencies = [ "compiler_builtins", "libc", diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 6af1cbb34b6c4..83029a8642097 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -41,7 +41,7 @@ dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] } fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] } [target.'cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_os = "hermit"))'.dependencies] -hermit-abi = { version = "0.1.13", features = ['rustc-dep-of-std'] } +hermit-abi = { version = "0.1.14", features = ['rustc-dep-of-std'] } [target.wasm32-wasi.dependencies] wasi = { version = "0.9.0", features = ['rustc-dep-of-std'], default-features = false } From 5f4eb27a0dc5d17e4a74f1a2d71a8f5a30916e3a Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Sun, 14 Jun 2020 19:21:44 +0200 Subject: [PATCH 35/45] Removing the TryFrom impl --- src/libstd/ffi/c_str.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 298f6c33457d8..6f7dc091897f4 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -1,7 +1,6 @@ use crate::ascii; use crate::borrow::{Borrow, Cow}; use crate::cmp::Ordering; -use crate::convert::TryFrom; use crate::error::Error; use crate::fmt::{self, Write}; use crate::io; @@ -854,19 +853,6 @@ impl From> for CString { } } -#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] -impl TryFrom> for CString { - type Error = FromBytesWithNulError; - - /// See the document about [`from_vec_with_nul`] for more - /// informations about the behaviour of this method. - /// - /// [`from_vec_with_nul`]: CString::from_vec_with_nul - fn try_from(value: Vec) -> Result { - Self::from_vec_with_nul(value) - } -} - #[stable(feature = "more_box_slice_clone", since = "1.29.0")] impl Clone for Box { #[inline] From 685f06612dc8842b734181e380eae0f9b1a9483f Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Sun, 14 Jun 2020 23:21:40 +0200 Subject: [PATCH 36/45] Add a new error type for the new method --- src/libstd/ffi/c_str.rs | 96 +++++++++++++++++++++++++++++++++++++++++ src/libstd/ffi/mod.rs | 2 + 2 files changed, 98 insertions(+) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 6f7dc091897f4..956100bca6a55 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -260,6 +260,32 @@ pub struct FromBytesWithNulError { kind: FromBytesWithNulErrorKind, } +/// An error indicating that a nul byte was not in the expected position. +/// +/// The vector used to create a [`CString`] must have one and only one nul byte, +/// positioned at the end. +/// +/// This error is created by the [`from_vec_with_nul`] method on [`CString`]. +/// See its documentation for more. +/// +/// [`CString`]: struct.CString.html +/// [`from_vec_with_nul`]: struct.CString.html#method.from_vec_with_nul +/// +/// # Examples +/// +/// ``` +/// #![feature(cstring_from_vec_with_nul)] +/// use std::ffi::{CString, FromVecWithNulError}; +/// +/// let _: FromVecWithNulError = CString::from_vec_with_nul(b"f\0oo".to_vec()).unwrap_err(); +/// ``` +#[derive(Clone, PartialEq, Eq, Debug)] +#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] +pub struct FromVecWithNulError { + error_kind: FromBytesWithNulErrorKind, + bytes: Vec, +} + #[derive(Clone, PartialEq, Eq, Debug)] enum FromBytesWithNulErrorKind { InteriorNul(usize), @@ -275,6 +301,59 @@ impl FromBytesWithNulError { } } +#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] +impl FromVecWithNulError { + /// Returns a slice of [`u8`]s bytes that were attempted to convert to a [`CString`]. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(cstring_from_vec_with_nul)] + /// use std::ffi::CString; + /// + /// // Some invalid bytes in a vector + /// let bytes = b"f\0oo".to_vec(); + /// + /// let value = CString::from_vec_with_nul(bytes.clone()); + /// + /// assert_eq!(&bytes[..], value.unwrap_err().as_bytes()); + /// ``` + /// + /// [`CString`]: struct.CString.html + pub fn as_bytes(&self) -> &[u8] { + &self.bytes[..] + } + + /// Returns the bytes that were attempted to convert to a [`CString`]. + /// + /// This method is carefully constructed to avoid allocation. It will + /// consume the error, moving out the bytes, so that a copy of the bytes + /// does not need to be made. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(cstring_from_vec_with_nul)] + /// use std::ffi::CString; + /// + /// // Some invalid bytes in a vector + /// let bytes = b"f\0oo".to_vec(); + /// + /// let value = CString::from_vec_with_nul(bytes.clone()); + /// + /// assert_eq!(bytes, value.unwrap_err().into_bytes()); + /// ``` + /// + /// [`CString`]: struct.CString.html + pub fn into_bytes(self) -> Vec { + self.bytes + } +} + /// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`]. /// /// `CString` is just a wrapper over a buffer of bytes with a nul @@ -1039,6 +1118,23 @@ impl fmt::Display for FromBytesWithNulError { } } +#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] +impl Error for FromVecWithNulError {} + +#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] +impl fmt::Display for FromVecWithNulError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.error_kind { + FromBytesWithNulErrorKind::InteriorNul(pos) => { + write!(f, "data provided contains an interior nul byte at pos {}", pos) + } + FromBytesWithNulErrorKind::NotNulTerminated => { + write!(f, "data provided is not nul terminated") + } + } + } +} + impl IntoStringError { /// Consumes this error, returning original [`CString`] which generated the /// error. diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index 5aca7b7476a52..f442d7fde1a5e 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -157,6 +157,8 @@ #[stable(feature = "cstr_from_bytes", since = "1.10.0")] pub use self::c_str::FromBytesWithNulError; +#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] +pub use self::c_str::FromVecWithNulError; #[stable(feature = "rust1", since = "1.0.0")] pub use self::c_str::{CStr, CString, IntoStringError, NulError}; From 47cc5cca7e64a434fa15680b7dcc621ca6f1abbf Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Sun, 14 Jun 2020 23:22:36 +0200 Subject: [PATCH 37/45] Update to use the new error type and correctly compile the doc tests --- src/libstd/ffi/c_str.rs | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 956100bca6a55..3537a9f8656a2 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -234,18 +234,14 @@ pub struct NulError(usize, Vec); /// An error indicating that a nul byte was not in the expected position. /// -/// The slice used to create a [`CStr`] or the vector used to create a -/// [`CString`] must have one and only one nul byte, positioned at the end. +/// The slice used to create a [`CStr`] must have one and only one nul byte, +/// positioned at the end. /// -/// This error is created by the -/// [`from_bytes_with_nul`][`CStr::from_bytes_with_nul`] method on -/// [`CStr`] or the [`from_vec_with_nul`][`CString::from_vec_with_nul`] method -/// on [`CString`]. See their documentation for more. +/// This error is created by the [`from_bytes_with_nul`] method on [`CStr`]. +/// See its documentation for more. /// /// [`CStr`]: struct.CStr.html -/// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul -/// [`CString`]: struct.CString.html -/// [`CString::from_vec_with_nul`]: struct.CString.html#method.from_vec_with_nul +/// [`from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul /// /// # Examples /// @@ -726,6 +722,7 @@ impl CString { /// # Example /// /// ``` + /// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::CString; /// assert_eq!( /// unsafe { CString::from_vec_with_nul_unchecked(b"abc\0".to_vec()) }, @@ -753,27 +750,29 @@ impl CString { /// called without the ending nul byte. /// /// ``` + /// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::CString; /// assert_eq!( /// CString::from_vec_with_nul(b"abc\0".to_vec()) /// .expect("CString::from_vec_with_nul failed"), - /// CString::new(b"abc".to_vec()) + /// CString::new(b"abc".to_vec()).expect("CString::new failed") /// ); /// ``` /// /// A incorrectly formatted vector will produce an error. /// /// ``` - /// use std::ffi::{CString, FromBytesWithNulError}; + /// #![feature(cstring_from_vec_with_nul)] + /// use std::ffi::{CString, FromVecWithNulError}; /// // Interior nul byte - /// let _: FromBytesWithNulError = CString::from_vec_with_nul(b"a\0bc".to_vec()).unwrap_err(); + /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"a\0bc".to_vec()).unwrap_err(); /// // No nul byte - /// let _: FromBytesWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err(); + /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err(); /// ``` /// /// [`new`]: #method.new #[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] - pub fn from_vec_with_nul(v: Vec) -> Result { + pub fn from_vec_with_nul(v: Vec) -> Result { let nul_pos = memchr::memchr(0, &v); match nul_pos { Some(nul_pos) if nul_pos + 1 == v.len() => { @@ -781,8 +780,14 @@ impl CString { // of the vec. Ok(unsafe { Self::from_vec_with_nul_unchecked(v) }) } - Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)), - None => Err(FromBytesWithNulError::not_nul_terminated()), + Some(nul_pos) => Err(FromVecWithNulError { + error_kind: FromBytesWithNulErrorKind::InteriorNul(nul_pos), + bytes: v, + }), + None => Err(FromVecWithNulError { + error_kind: FromBytesWithNulErrorKind::NotNulTerminated, + bytes: v, + }), } } } From d221ffc68e543f4a38efcc2bd34f52145f89003b Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 14 Jun 2020 23:43:54 +0200 Subject: [PATCH 38/45] simplify conversion to IpAddr::V6 --- src/libstd/sys/hermit/net.rs | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs index 70c010e6232f8..cba8d6aaca61c 100644 --- a/src/libstd/sys/hermit/net.rs +++ b/src/libstd/sys/hermit/net.rs @@ -150,15 +150,7 @@ impl TcpStream { port, ), Ipv6(ref addr) => SocketAddr::new( - IpAddr::V6(Ipv6Addr::new( - ((addr.0[0] as u16) << 8) | addr.0[1] as u16, - ((addr.0[2] as u16) << 8) | addr.0[3] as u16, - ((addr.0[4] as u16) << 8) | addr.0[5] as u16, - ((addr.0[6] as u16) << 8) | addr.0[7] as u16, - ((addr.0[8] as u16) << 8) | addr.0[9] as u16, - ((addr.0[10] as u16) << 8) | addr.0[11] as u16, - ((addr.0[12] as u16) << 8) | addr.0[13] as u16, - ((addr.0[14] as u16) << 8) | addr.0[15] as u16)), + IpAddr::V6(Ipv6Addr::new(addr.0)), port, ), _ => { @@ -241,15 +233,7 @@ impl TcpListener { port, ), Ipv6(ref addr) => SocketAddr::new( - IpAddr::V6(Ipv6Addr::new( - ((addr.0[0] as u16) << 8) | addr.0[1] as u16, - ((addr.0[2] as u16) << 8) | addr.0[3] as u16, - ((addr.0[4] as u16) << 8) | addr.0[5] as u16, - ((addr.0[6] as u16) << 8) | addr.0[7] as u16, - ((addr.0[8] as u16) << 8) | addr.0[9] as u16, - ((addr.0[10] as u16) << 8) | addr.0[11] as u16, - ((addr.0[12] as u16) << 8) | addr.0[13] as u16, - ((addr.0[14] as u16) << 8) | addr.0[15] as u16)), + IpAddr::V6(Ipv6Addr::new(addr.0)), port, ), _ => { From 9d596b50f15dfff47fa2272ee63cdc9aeb9307fa Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Mon, 15 Jun 2020 07:28:53 +0200 Subject: [PATCH 39/45] changes to pass the format check --- src/libstd/sys/hermit/net.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs index cba8d6aaca61c..ced554d8790a7 100644 --- a/src/libstd/sys/hermit/net.rs +++ b/src/libstd/sys/hermit/net.rs @@ -149,13 +149,10 @@ impl TcpStream { IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])), port, ), - Ipv6(ref addr) => SocketAddr::new( - IpAddr::V6(Ipv6Addr::new(addr.0)), - port, - ), + Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::new(addr.0)), port), _ => { return Err(io::Error::new(ErrorKind::Other, "peer_addr failed")); - }, + } }; Ok(saddr) @@ -232,13 +229,10 @@ impl TcpListener { IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])), port, ), - Ipv6(ref addr) => SocketAddr::new( - IpAddr::V6(Ipv6Addr::new(addr.0)), - port, - ), + Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::new(addr.0)), port), _ => { return Err(io::Error::new(ErrorKind::Other, "accept failed")); - }, + } }; Ok((TcpStream(Arc::new(Socket(handle))), saddr)) From 810ba395638f622b4e7f11c2f056382db4d2fa05 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Mon, 15 Jun 2020 08:07:56 +0200 Subject: [PATCH 40/45] remove obsolete line --- src/libstd/sys/hermit/net.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs index ced554d8790a7..fbb562fa51051 100644 --- a/src/libstd/sys/hermit/net.rs +++ b/src/libstd/sys/hermit/net.rs @@ -35,7 +35,6 @@ impl Drop for Socket { } } - #[derive(Clone)] pub struct TcpStream(Arc); From aa53a037a286a05c88e61ca008d90354cccb1512 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Mon, 15 Jun 2020 08:43:08 +0200 Subject: [PATCH 41/45] Revert "changes to pass the format check" This reverts commit 9d596b50f15dfff47fa2272ee63cdc9aeb9307fa. --- src/libstd/sys/hermit/net.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs index fbb562fa51051..8f96f8622c661 100644 --- a/src/libstd/sys/hermit/net.rs +++ b/src/libstd/sys/hermit/net.rs @@ -148,10 +148,13 @@ impl TcpStream { IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])), port, ), - Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::new(addr.0)), port), + Ipv6(ref addr) => SocketAddr::new( + IpAddr::V6(Ipv6Addr::new(addr.0)), + port, + ), _ => { return Err(io::Error::new(ErrorKind::Other, "peer_addr failed")); - } + }, }; Ok(saddr) @@ -228,10 +231,13 @@ impl TcpListener { IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])), port, ), - Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::new(addr.0)), port), + Ipv6(ref addr) => SocketAddr::new( + IpAddr::V6(Ipv6Addr::new(addr.0)), + port, + ), _ => { return Err(io::Error::new(ErrorKind::Other, "accept failed")); - } + }, }; Ok((TcpStream(Arc::new(Socket(handle))), saddr)) From 9c9f21fb23ae59012e7aba162e1105d26fcd119b Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Mon, 15 Jun 2020 08:43:44 +0200 Subject: [PATCH 42/45] Revert "simplify conversion to IpAddr::V6" This reverts commit d221ffc68e543f4a38efcc2bd34f52145f89003b. --- src/libstd/sys/hermit/net.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs index 8f96f8622c661..a02f1131329ee 100644 --- a/src/libstd/sys/hermit/net.rs +++ b/src/libstd/sys/hermit/net.rs @@ -149,7 +149,15 @@ impl TcpStream { port, ), Ipv6(ref addr) => SocketAddr::new( - IpAddr::V6(Ipv6Addr::new(addr.0)), + IpAddr::V6(Ipv6Addr::new( + ((addr.0[0] as u16) << 8) | addr.0[1] as u16, + ((addr.0[2] as u16) << 8) | addr.0[3] as u16, + ((addr.0[4] as u16) << 8) | addr.0[5] as u16, + ((addr.0[6] as u16) << 8) | addr.0[7] as u16, + ((addr.0[8] as u16) << 8) | addr.0[9] as u16, + ((addr.0[10] as u16) << 8) | addr.0[11] as u16, + ((addr.0[12] as u16) << 8) | addr.0[13] as u16, + ((addr.0[14] as u16) << 8) | addr.0[15] as u16)), port, ), _ => { @@ -232,7 +240,15 @@ impl TcpListener { port, ), Ipv6(ref addr) => SocketAddr::new( - IpAddr::V6(Ipv6Addr::new(addr.0)), + IpAddr::V6(Ipv6Addr::new( + ((addr.0[0] as u16) << 8) | addr.0[1] as u16, + ((addr.0[2] as u16) << 8) | addr.0[3] as u16, + ((addr.0[4] as u16) << 8) | addr.0[5] as u16, + ((addr.0[6] as u16) << 8) | addr.0[7] as u16, + ((addr.0[8] as u16) << 8) | addr.0[9] as u16, + ((addr.0[10] as u16) << 8) | addr.0[11] as u16, + ((addr.0[12] as u16) << 8) | addr.0[13] as u16, + ((addr.0[14] as u16) << 8) | addr.0[15] as u16)), port, ), _ => { From 6c983a733550ff37cb603f409901f3b3d0eaa8c2 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Mon, 15 Jun 2020 08:53:58 +0200 Subject: [PATCH 43/45] use Ipv6Addr::from to build the IPv6 address --- src/libstd/sys/hermit/net.rs | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs index a02f1131329ee..6410dec756d24 100644 --- a/src/libstd/sys/hermit/net.rs +++ b/src/libstd/sys/hermit/net.rs @@ -148,18 +148,7 @@ impl TcpStream { IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])), port, ), - Ipv6(ref addr) => SocketAddr::new( - IpAddr::V6(Ipv6Addr::new( - ((addr.0[0] as u16) << 8) | addr.0[1] as u16, - ((addr.0[2] as u16) << 8) | addr.0[3] as u16, - ((addr.0[4] as u16) << 8) | addr.0[5] as u16, - ((addr.0[6] as u16) << 8) | addr.0[7] as u16, - ((addr.0[8] as u16) << 8) | addr.0[9] as u16, - ((addr.0[10] as u16) << 8) | addr.0[11] as u16, - ((addr.0[12] as u16) << 8) | addr.0[13] as u16, - ((addr.0[14] as u16) << 8) | addr.0[15] as u16)), - port, - ), + Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port), _ => { return Err(io::Error::new(ErrorKind::Other, "peer_addr failed")); }, @@ -239,18 +228,7 @@ impl TcpListener { IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])), port, ), - Ipv6(ref addr) => SocketAddr::new( - IpAddr::V6(Ipv6Addr::new( - ((addr.0[0] as u16) << 8) | addr.0[1] as u16, - ((addr.0[2] as u16) << 8) | addr.0[3] as u16, - ((addr.0[4] as u16) << 8) | addr.0[5] as u16, - ((addr.0[6] as u16) << 8) | addr.0[7] as u16, - ((addr.0[8] as u16) << 8) | addr.0[9] as u16, - ((addr.0[10] as u16) << 8) | addr.0[11] as u16, - ((addr.0[12] as u16) << 8) | addr.0[13] as u16, - ((addr.0[14] as u16) << 8) | addr.0[15] as u16)), - port, - ), + Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port), _ => { return Err(io::Error::new(ErrorKind::Other, "accept failed")); }, From a8e3746e9160b8a433c95df7114e5760592a62e8 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Mon, 15 Jun 2020 09:29:32 +0200 Subject: [PATCH 44/45] add comment about the usage of Arc --- src/libstd/sys/hermit/net.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs index 6410dec756d24..9146dfc55f438 100644 --- a/src/libstd/sys/hermit/net.rs +++ b/src/libstd/sys/hermit/net.rs @@ -35,6 +35,9 @@ impl Drop for Socket { } } +// Arc is used to count the number of used sockets. +// Only if all sockets are released, the drop +// method will close the socket. #[derive(Clone)] pub struct TcpStream(Arc); From 76f1581a25a27029279bb5eac17971ba68df1dbe Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Mon, 15 Jun 2020 10:05:14 +0200 Subject: [PATCH 45/45] remove obsolete , to pass the format check --- src/libstd/sys/hermit/net.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs index 9146dfc55f438..9e588c4265ac2 100644 --- a/src/libstd/sys/hermit/net.rs +++ b/src/libstd/sys/hermit/net.rs @@ -154,7 +154,7 @@ impl TcpStream { Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port), _ => { return Err(io::Error::new(ErrorKind::Other, "peer_addr failed")); - }, + } }; Ok(saddr) @@ -234,7 +234,7 @@ impl TcpListener { Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port), _ => { return Err(io::Error::new(ErrorKind::Other, "accept failed")); - }, + } }; Ok((TcpStream(Arc::new(Socket(handle))), saddr))