diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 355f282921537..bf3c22744f165 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -428,11 +428,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/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/bootstrap/builder.rs b/src/bootstrap/builder.rs index c4f29927cf4a8..ea5300bdfc04c 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -373,7 +373,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 aeabb227cf5e9..b8c5751565838 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -930,13 +930,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 590845b33cda7..a052d0879a3db 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -492,12 +492,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 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_arena/lib.rs b/src/librustc_arena/lib.rs index 4da336f8e288d..4a2a0de0e211f 100644 --- a/src/librustc_arena/lib.rs +++ b/src/librustc_arena/lib.rs @@ -602,7 +602,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, @@ -611,17 +611,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!() @@ -630,18 +630,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); } @@ -659,7 +668,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 d7946ad009415..a722a88a7a102 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_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 3fb5e04efc922..99ef226f94aae 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -439,6 +439,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"), E0761: include_str!("./error_codes/E0761.md"), E0762: include_str!("./error_codes/E0762.md"), 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_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_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_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 12f7a9c0ca502..9cfa11dd7c813 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -2035,8 +2035,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 f4c86ddae604e..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 @@ -1,14 +1,15 @@ //! 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}; +use rustc_errors::{struct_span_err, Applicability, ErrorReported}; +use rustc_hir::{GenericBound, ItemKind, Lifetime, LifetimeName, TyKind}; 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( _, @@ -17,18 +18,36 @@ 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)?; - let (fn_return_span, is_dyn) = - self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?; - if sub_r == &RegionKind::ReStatic { + 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)?; + 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 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..."); + let (lifetime_name, lifetime) = if sup_r.has_name() { + (sup_r.to_string(), format!("lifetime `{}`", sup_r)) + } else { + ("'_".to_owned(), "an anonymous lifetime `'_`".to_string()) + }; + let mut err = struct_span_err!( + self.tcx().sess, + sp, + E0759, + "cannot infer an appropriate 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. if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span())) @@ -38,41 +57,146 @@ 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() { - err.span_label(sup_origin.span(), "...is captured here..."); - err.span_label(return_sp, "...and required to be `'static` by this"); + 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 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) } + // | ---- ^ + err.span_label( + sup_origin.span(), + "...is captured here, requiring it to live as long as `'static`", + ); } else { - err.span_label(return_sp, "...is required to be `'static` by this..."); - err.span_label(sup_origin.span(), "...and is captured here"); + err.span_label(sup_origin.span(), "...is captured 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 to be `'static` here", + "...is captured and required to live as long as `'static` here", ); } - 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() { - 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 + '_)` - err.span_suggestion_verbose( - fn_return_span.shrink_to_hi(), - &msg, - format!(" + {}", lifetime_name), - Applicability::MaybeIncorrect, - ); + + 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 the lifetime of {}", 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); + let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind { + opaque + } else { + err.emit(); + return Some(ErrorReported); + }; + + if let Some(span) = opaque + .bounds + .iter() + .filter_map(|arg| match arg { + GenericBound::Outlives(Lifetime { + name: LifetimeName::Static, + span, + .. + }) => Some(*span), + _ => None, + }) + .next() + { + err.span_suggestion_verbose( + span, + &format!("{} `impl Trait`'s {}", consider, explicit_static), + lifetime_name, + Applicability::MaybeIncorrect, + ); + err.span_suggestion_verbose( + param_info.param_ty_span, + add_static_bound, + param_info.param_ty.to_string(), + Applicability::MaybeIncorrect, + ); + } else { + err.span_suggestion_verbose( + fn_return.span.shrink_to_hi(), + &format!( + "{declare} `impl Trait` {captures}, {explicit}", + declare = declare, + captures = captures, + explicit = explicit, + ), + plus_lt, + Applicability::MaybeIncorrect, + ); + }; + } + TyKind::TraitObject(_, lt) => match lt.name { + LifetimeName::ImplicitObjectLifetimeDefault => { + err.span_suggestion_verbose( + fn_return.span.shrink_to_hi(), + &format!( + "{declare} trait object {captures}, {explicit}", + declare = declare, + captures = captures, + explicit = explicit, + ), + plus_lt, + Applicability::MaybeIncorrect, + ); + } + _ => { + err.span_suggestion_verbose( + lt.span, + &format!("{} trait object's {}", consider, explicit_static), + lifetime_name, + Applicability::MaybeIncorrect, + ); + err.span_suggestion_verbose( + param_info.param_ty_span, + add_static_bound, + param_info.param_ty.to_string(), + Applicability::MaybeIncorrect, + ); + } + }, + _ => {} + } } err.emit(); return Some(ErrorReported); 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 44944a9fb265a..5b2f000a93fca 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 1dc22c10c8e7a..feefdf299a95a 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 129f9691ea521..84750a9ead02e 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. @@ -1957,8 +1988,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/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..a2812e117ed39 100644 --- a/src/librustc_middle/ty/diagnostics.rs +++ b/src/librustc_middle/ty/diagnostics.rs @@ -236,21 +236,24 @@ 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, .. }, + hir::Lifetime { + name: hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static, + .. + }, ) = ty.kind { - self.0.push(ty.span); + self.0.push(ty); } } } 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 7550be39d4ab0..fad96aa86cc0a 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -2409,8 +2409,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_middle/ty/util.rs b/src/librustc_middle/ty/util.rs index c61e27528cef1..866a35ebfa60d 100644 --- a/src/librustc_middle/ty/util.rs +++ b/src/librustc_middle/ty/util.rs @@ -878,7 +878,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_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_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", 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, 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/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index 1b72a4bf84f19..d31e04cffd55f 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -1747,24 +1747,41 @@ 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 msg = format!( + "insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `{}` representable", + path, + ); + 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, + ); + } else { + err.help(&msg); + } + err.emit(); } /// Summarizes information diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7b8f180219688..a409e20953da1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2387,11 +2387,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/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 } diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index b324b1618966b..dca1fdde48242 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -234,15 +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`] must have one and only one nul -/// byte at the end of the slice. +/// 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`]. See its 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 +/// [`from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul /// /// # Examples /// @@ -257,6 +256,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), @@ -272,6 +297,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 @@ -643,6 +721,86 @@ 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 + /// + /// ``` + /// #![feature(cstring_from_vec_with_nul)] + /// 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()) } + /// ); + /// ``` + #[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() } + } + + /// 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. + /// + /// ``` + /// #![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()).expect("CString::new failed") + /// ); + /// ``` + /// + /// A incorrectly formatted vector will produce an error. + /// + /// ``` + /// #![feature(cstring_from_vec_with_nul)] + /// use std::ffi::{CString, FromVecWithNulError}; + /// // Interior nul byte + /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"a\0bc".to_vec()).unwrap_err(); + /// // No nul byte + /// 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 { + 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(FromVecWithNulError { + error_kind: FromBytesWithNulErrorKind::InteriorNul(nul_pos), + bytes: v, + }), + None => Err(FromVecWithNulError { + error_kind: FromBytesWithNulErrorKind::NotNulTerminated, + bytes: v, + }), + } + } } // Turns this `CString` into an empty string to prevent @@ -976,6 +1134,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}; diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index b780340884e1f..b8fa1a7f744d3 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); @@ -1268,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()); } } diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 797b22fdd1279..8478457eabfc2 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -107,6 +107,60 @@ 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. +/// +/// ``` +/// use std::sync::{Arc, Mutex}; +/// use std::thread; +/// +/// const N: usize = 3; +/// +/// let data_mutex = Arc::new(Mutex::new(vec![1, 2, 3, 4])); +/// let res_mutex = Arc::new(Mutex::new(0)); +/// +/// let mut threads = Vec::with_capacity(N); +/// (0..N).for_each(|_| { +/// let data_mutex_clone = Arc::clone(&data_mutex); +/// let res_mutex_clone = Arc::clone(&res_mutex); +/// +/// threads.push(thread::spawn(move || { +/// 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); +/// drop(data); +/// *res_mutex_clone.lock().unwrap() += result; +/// })); +/// }); +/// +/// 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` 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. +/// 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. +/// *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(), 800); +/// ``` #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "mutex_type")] pub struct Mutex { diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs index 5b5379c8b0581..9e588c4265ac2 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,33 @@ pub fn init() -> io::Result<()> { Ok(()) } -pub struct TcpStream(abi::Handle); +#[derive(Debug, Clone)] +pub struct Socket(abi::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); + } +} + +// 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); 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 +59,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 +67,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 +106,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 +130,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 +143,21 @@ 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::from(addr.0)), port), + _ => { + return Err(io::Error::new(ErrorKind::Other, "peer_addr failed")); + } + }; + + Ok(saddr) } pub fn socket_addr(&self) -> io::Result { @@ -133,34 +165,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 +198,50 @@ 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::from(addr.0)), 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<()> { diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index af8fc2cd2ab45..0f58b158904db 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -1,13 +1,14 @@ -error: 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) { | ^^^^^ | | - | data with this lifetime... + | this data with an anonymous lifetime `'_`... | ...is captured here... LL | foo(|| self.bar()).await; - | --- ...and required to be `'static` by this + | --- ...and is required to live as long as `'static` here error: aborting due to previous error +For more information about this error, try `rustc --explain E0759`. 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..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 @@ -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 cannot infer an appropriate lifetime + +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..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,47 +1,113 @@ -error: 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 } - | ---- --------- ^ ...and is captured here - | | | - | | ...is required to be `'static` by this... - | data with this lifetime... + | ---- ^ ...is captured 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 the anonymous lifetime #1 defined on the function body at 3:1 +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 } | ^^^^ -error: 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 } - | ------- --------- ^ ...and is captured here - | | | - | | ...is required to be `'static` by this... - | data with this lifetime... + | ------- ^ ...is captured here... + | | + | 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 +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 } | ^^^^ -error: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:12:69 +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 } + | ---- ^ ...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 the lifetime of argument `x` + | +LL | fn elided2(x: &i32) -> impl Copy + '_ { x } + | ^^ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x } + | ^^^^^^^^^^^^ + +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 } + | ------- ^ ...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 the lifetime of argument `x` + | +LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } + | ^^ +help: alternatively, add an explicit `'static` bound to this reference + | +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 + | +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[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 } - | ------- -------------------------------- ^ ...and is captured here - | | | - | | ...is required to be `'static` by this... - | data with this lifetime... + | ------- this data with lifetime `'a`... ^ ...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 function body at 12:15 +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 the lifetime of argument `x` | -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 } + | ^^ +help: alternatively, add an explicit `'static` bound to this reference + | +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: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 +116,72 @@ 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[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) } + | ---- ^ ...is captured here, requiring it to live as long as `'static` + | | + | this data with 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) } + | ^^^^ + +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) } + | ------- ^ ...is captured here, requiring it to live as long as `'static` + | | + | this data with 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) } + | ^^^^ + +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) } + | ---- ^ ...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 the lifetime of argument `x` + | +LL | fn elided4(x: &i32) -> Box { Box::new(x) } + | ^^ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn elided4(x: &'static i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^^ + +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) } + | ------- 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 the lifetime of argument `x` + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^^ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn explicit4<'a>(x: &'static i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^^ + +error: aborting due to 12 previous errors -Some errors have detailed explanations: E0310, E0623. +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 1c3a5979ee55b..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,36 +1,43 @@ -error: 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 { - | ----- ----------------------- ...is required to be `'static` by this... - | | - | data with this lifetime... + | ----- this data with an anonymous lifetime `'_`... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | - | ...and is captured here + | ...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 +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 + '_ { | ^^^^ -error: 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 { - | -------- ----------------------- ...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 + | ...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 +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 { | ^^^^ error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/infinite/infinite-tag-type-recursion.stderr b/src/test/ui/infinite/infinite-tag-type-recursion.stderr index 11f82b842ba6f..6d1df4fda2eb0 100644 --- a/src/test/ui/infinite/infinite-tag-type-recursion.stderr +++ b/src/test/ui/infinite/infinite-tag-type-recursion.stderr @@ -6,7 +6,10 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `MList` representable + | +LL | enum MList { Cons(isize, Box), 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-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 02d33aae023ff..919594fc9af4b 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -1,18 +1,16 @@ -error: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/issue-16922.rs:4:14 | LL | fn foo(value: &T) -> Box { - | -- data with this lifetime... + | -- this data with an anonymous lifetime `'_`... LL | Box::new(value) as Box - | ---------^^^^^- - | | | - | | ...and is captured here - | ...is required to be `'static` by this... + | ^^^^^ ...is captured here, requiring it to live as long as `'static` | -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 declare that the trait object captures data from argument `value`, you can add an explicit `'_` lifetime bound | LL | fn foo(value: &T) -> Box { | ^^^^ error: aborting due to previous error +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/issues/issue-17431-1.stderr b/src/test/ui/issues/issue-17431-1.stderr index eb5a1366e8953..58d087ca1998b 100644 --- a/src/test/ui/issues/issue-17431-1.stderr +++ b/src/test/ui/issues/issue-17431-1.stderr @@ -2,11 +2,14 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable + | +LL | struct Foo { foo: Box>> } + | ^^^^ ^ 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..eba4bf6d1d5ea 100644 --- a/src/test/ui/issues/issue-17431-2.stderr +++ b/src/test/ui/issues/issue-17431-2.stderr @@ -2,21 +2,27 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable + | +LL | struct Baz { q: Box> } + | ^^^^ ^ 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 (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable + | +LL | struct Foo { q: Box> } + | ^^^^ ^ 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..f6b15d0528ae8 100644 --- a/src/test/ui/issues/issue-17431-3.stderr +++ b/src/test/ui/issues/issue-17431-3.stderr @@ -2,11 +2,14 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable + | +LL | struct Foo { foo: Box>> } + | ^^^^ ^ 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..aa709e1ad5183 100644 --- a/src/test/ui/issues/issue-17431-4.stderr +++ b/src/test/ui/issues/issue-17431-4.stderr @@ -2,11 +2,14 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable + | +LL | struct Foo { foo: Box>>>, 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..1558cffb036b3 100644 --- a/src/test/ui/issues/issue-17431-5.stderr +++ b/src/test/ui/issues/issue-17431-5.stderr @@ -2,11 +2,14 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable + | +LL | struct Bar { x: Box> , 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..f2aa2a79c8200 100644 --- a/src/test/ui/issues/issue-17431-6.stderr +++ b/src/test/ui/issues/issue-17431-6.stderr @@ -6,7 +6,10 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable + | +LL | enum Foo { X(Box>>) } + | ^^^^ ^ 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..684c3089e85ec 100644 --- a/src/test/ui/issues/issue-17431-7.stderr +++ b/src/test/ui/issues/issue-17431-7.stderr @@ -6,7 +6,10 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable + | +LL | enum Foo { Voo(Box>>) } + | ^^^^ ^ 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..d152ffde4e57d 100644 --- a/src/test/ui/issues/issue-2718-a.stderr +++ b/src/test/ui/issues/issue-2718-a.stderr @@ -7,7 +7,10 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `pingpong::Pong` representable + | +LL | pub struct Pong(Box>); + | ^^^^ ^ 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..87ee36df21696 100644 --- a/src/test/ui/issues/issue-3008-1.stderr +++ b/src/test/ui/issues/issue-3008-1.stderr @@ -7,7 +7,10 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable + | +LL | BarSome(Box) + | ^^^^ ^ 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..369a19d37e6f6 100644 --- a/src/test/ui/issues/issue-3008-2.stderr +++ b/src/test/ui/issues/issue-3008-2.stderr @@ -2,11 +2,14 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable + | +LL | struct Bar { x: Box } + | ^^^^ ^ 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..0b162eff94a7c 100644 --- a/src/test/ui/issues/issue-3008-3.stderr +++ b/src/test/ui/issues/issue-3008-3.stderr @@ -6,7 +6,10 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `E2` representable + | +LL | enum E2 { V2(Box>, 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..7b17e91421660 100644 --- a/src/test/ui/issues/issue-3779.stderr +++ b/src/test/ui/issues/issue-3779.stderr @@ -5,9 +5,12 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `S` representable + | +LL | element: Box> + | ^^^^ ^ 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..b7c799e163cee 100644 --- a/src/test/ui/issues/issue-57271.stderr +++ b/src/test/ui/issues/issue-57271.stderr @@ -7,7 +7,10 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `ObjectType` representable + | +LL | Array(Box), + | ^^^^ ^ error[E0072]: recursive type `TypeSignature` has infinite size --> $DIR/issue-57271.rs:19:1 @@ -18,7 +21,10 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `TypeSignature` representable + | +LL | Object(Box), + | ^^^^ ^ error: aborting due to 2 previous errors 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 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..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,13 +1,13 @@ -error: 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 { - | --------------- data with this lifetime... + | --------------- this data with an anonymous lifetime `'_`... ... LL | ss.r - | ^^^^ ...is captured and required to be `'static` here + | ^^^^ ...is captured and required to live as long as `'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 declare that the trait object captures data from argument `ss`, you can add an explicit `'_` lifetime bound | LL | fn load(ss: &mut SomeStruct) -> Box { | ^^^^ @@ -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, E0759. +For more information about an error, try `rustc --explain E0621`. diff --git a/src/test/ui/recursion/recursive-enum.stderr b/src/test/ui/recursion/recursive-enum.stderr index e4674b57a6d21..ab4709d8e709e 100644 --- a/src/test/ui/recursion/recursive-enum.stderr +++ b/src/test/ui/recursion/recursive-enum.stderr @@ -6,7 +6,10 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `List` representable + | +LL | enum List { Cons(T, Box>), Nil } + | ^^^^ ^ error: aborting due to previous error 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..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,61 +1,76 @@ -error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/region-object-lifetime-in-coercion.rs:8:37 +error[E0759]: 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]` + | ----- this data with an anonymous lifetime `'_`... LL | let x: Box = Box::new(v); - | ^^^^^^^^^^^ lifetime `'static` required + | ^ ...is captured here, requiring it to live as long as `'static` + | +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` + | +LL | fn a(v: &[u8]) -> Box { + | ^^ +help: alternatively, add an explicit `'static` bound to this reference + | +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[E0759]: 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]` + | ----- this data with an anonymous lifetime `'_`... LL | Box::new(v) - | ^^^^^^^^^^^ lifetime `'static` required + | ^ ...is captured here, requiring it to live as long as `'static` + | +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` + | +LL | fn b(v: &[u8]) -> Box { + | ^^ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn b(v: &'static [u8]) -> Box { + | ^^^^^^^^^^^^^ -error: cannot infer an appropriate lifetime - --> $DIR/region-object-lifetime-in-coercion.rs:20:14 +error[E0759]: 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 an anonymous lifetime `'_`... ... LL | Box::new(v) - | ---------^- - | | | - | | ...and is captured here - | ...is required to be `'static` by this... + | ^ ...is captured here, requiring it to live as long as `'static` | -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 declare that the trait object captures data from argument `v`, you can add an explicit `'_` lifetime bound | 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 +79,5 @@ LL | Box::new(v) error: aborting due to 4 previous errors -Some errors have detailed explanations: E0495, E0621. +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 147f7f3541816..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,28 +1,20 @@ -error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements +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 { + | ------------------ this data with lifetime `'a`... 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 + | ^^^ ...is captured here, requiring it to live as long as `'static` | -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 to the lifetime of argument `v` | -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, add an explicit `'static` bound to this reference | -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`. +For more information about this error, try `rustc --explain E0759`. 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..850d81940791f 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,20 @@ -error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements +error[E0759]: 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 - | ^^^ - | -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 + | ^^^ ...is captured here, requiring it to live as long as `'static` | -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 to the lifetime of argument `v` | -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, add an explicit `'static` bound to this reference | -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`. +For more information about this error, try `rustc --explain E0759`. 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..67eee3bb6e281 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -1,12 +1,21 @@ -error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/regions-proc-bound-capture.rs:9:5 +error[E0759]: 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> { + | ------ this data with an anonymous 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 }) + | ^^^^^^^^^^^^^^ ...is captured here, requiring it to live as long as `'static` + | +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` + | +LL | fn static_proc(x: &isize) -> Box (isize) + '_> { + | ^^ +help: alternatively, add an explicit `'static` bound to this reference + | +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`. +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 1aeabce5e8aaf..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,11 +1,12 @@ -error: 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 } - | ^^^^ ---------- ---------- ...and required to be `'static` by this + | ^^^^ ---------- ---------- ...and is required to live as long as `'static` here | | | - | | data with this lifetime... + | | this data with an anonymous lifetime `'_`... | ...is captured here... error: aborting due to previous error +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 04c475be787b8..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,16 +1,21 @@ -error: 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 } - | ---------- ---------- ^^^^ ...and is captured here - | | | - | | ...is required to be `'static` by this... - | data with this lifetime... + | ---------- ^^^^ ...is captured 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 the anonymous lifetime #1 defined on the method body at 6:5 +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 } | ^^^^ error: aborting due to previous error +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/sized-cycle-note.stderr b/src/test/ui/sized-cycle-note.stderr index 95bdc34942645..45062c2ea6c72 100644 --- a/src/test/ui/sized-cycle-note.stderr +++ b/src/test/ui/sized-cycle-note.stderr @@ -2,21 +2,27 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable + | +LL | struct Baz { q: Box> } + | ^^^^ ^ 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 (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable + | +LL | struct Foo { q: Box> } + | ^^^^ ^ 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..06493f05142e6 100644 --- a/src/test/ui/span/E0072.stderr +++ b/src/test/ui/span/E0072.stderr @@ -5,9 +5,12 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable + | +LL | tail: Box>, + | ^^^^ ^ 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..55128347f7404 100644 --- a/src/test/ui/span/multiline-span-E0072.stderr +++ b/src/test/ui/span/multiline-span-E0072.stderr @@ -6,11 +6,14 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable + | +LL | tail: Box>, + | ^^^^ ^ 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..fb1d98b58dfbe 100644 --- a/src/test/ui/span/recursive-type-field.stderr +++ b/src/test/ui/span/recursive-type-field.stderr @@ -4,9 +4,12 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable + | +LL | bar: Box>, + | ^^^^ ^ error[E0072]: recursive type `Bar` has infinite size --> $DIR/recursive-type-field.rs:8:1 @@ -14,18 +17,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/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 5cf170d566ca9..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,20 +6,23 @@ LL | fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ | | | help: consider introducing lifetime `'a` here: `'a,` -error: 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() - | ------ ------------- ...is required to be `'static` by this... - | | - | data with this lifetime... + | ------ this data with an anonymous lifetime `'_`... ... LL | / move || { LL | | *dest = g.get(); LL | | } - | |_____^ ...and is captured here + | |_____^ ...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 +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() + '_ | ^^^^ @@ -122,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, E0759. For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/type/type-recursive.stderr b/src/test/ui/type/type-recursive.stderr index 72bf372e561d6..d6d32cc5d6f39 100644 --- a/src/test/ui/type/type-recursive.stderr +++ b/src/test/ui/type/type-recursive.stderr @@ -5,9 +5,12 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `T1` representable + | +LL | foolish: Box + | ^^^^ ^ 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 3577dd59289e5..dda5de431d309 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -1,16 +1,17 @@ -error: 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> { - | ---- data with this 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 to live as long as `'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 declare that the trait object captures data from argument `items`, you can add an explicit `'_` lifetime bound | LL | fn a(items: &[T]) -> Box + '_> { | ^^^^ error: aborting due to previous error +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/union/union-nonrepresentable.stderr b/src/test/ui/union/union-nonrepresentable.stderr index 746c1033ea348..c54d04de12c50 100644 --- a/src/test/ui/union/union-nonrepresentable.stderr +++ b/src/test/ui/union/union-nonrepresentable.stderr @@ -5,9 +5,12 @@ 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 (e.g., a `Box`, `Rc`, or `&`) to make `U` representable + | +LL | b: Box, + | ^^^^ ^ error: aborting due to previous error 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 {