diff options
255 files changed, 3179 insertions, 2315 deletions
diff --git a/.gitmodules b/.gitmodules index 21bce3c7fa0..a524098845a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -34,7 +34,7 @@ [submodule "src/llvm-project"] path = src/llvm-project url = https://github.com/rust-lang/llvm-project.git - branch = rustc/14.0-2022-03-22 + branch = rustc/14.0-2022-06-20 [submodule "src/doc/embedded-book"] path = src/doc/embedded-book url = https://github.com/rust-embedded/book.git diff --git a/Cargo.lock b/Cargo.lock index 347341b5ff7..96d9449db57 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4280,6 +4280,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_hir", + "rustc_macros", "rustc_middle", "rustc_session", "rustc_span", diff --git a/RELEASES.md b/RELEASES.md index 3d88891ad21..7479735012c 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -29,7 +29,6 @@ Compiler Libraries --------- -- [Move `CStr` to libcore, and `CString` to liballoc][94079] - [Windows: Use a pipe relay for chaining pipes][95841] - [Replace Linux Mutex and Condvar with futex based ones.][95035] - [Replace RwLock by a futex based one on Linux][95801] @@ -90,7 +89,6 @@ and related tools. [93313]: https://github.com/rust-lang/rust/pull/93313/ [93969]: https://github.com/rust-lang/rust/pull/93969/ -[94079]: https://github.com/rust-lang/rust/pull/94079/ [94206]: https://github.com/rust-lang/rust/pull/94206/ [94457]: https://github.com/rust-lang/rust/pull/94457/ [94775]: https://github.com/rust-lang/rust/pull/94775/ diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index a1233d62cb0..708fe8719a1 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -1,4 +1,6 @@ -use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{ + struct_span_err, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, ErrorGuaranteed, MultiSpan, +}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; @@ -476,10 +478,11 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] fn struct_span_err_with_code<S: Into<MultiSpan>>( &self, sp: S, - msg: &str, + msg: impl Into<DiagnosticMessage>, code: DiagnosticId, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { self.infcx.tcx.sess.struct_span_err_with_code(sp, msg, code) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 8f3699553d9..e60e11f11df 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -879,7 +879,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { } let mut found = false; - tcx.fold_regions(tcx.type_of(body_parent_did), &mut true, |r: ty::Region<'tcx>, _| { + tcx.fold_regions(tcx.type_of(body_parent_did), |r: ty::Region<'tcx>, _| { if *r == ty::ReEarlyBound(region) { found = true; } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 8ef2974c372..a2df072aa31 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -6,6 +6,7 @@ #![feature(let_else)] #![feature(min_specialization)] #![feature(never_type)] +#![feature(rustc_attrs)] #![feature(stmt_expr_attributes)] #![feature(trusted_step)] #![feature(try_blocks)] diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 0fe3b45bc7c..f5c9392948b 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1009,7 +1009,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { debug!("try_promote_type_test_subject(ty = {:?})", ty); - let ty = tcx.fold_regions(ty, &mut false, |r, _depth| { + let ty = tcx.fold_regions(ty, |r, _depth| { let region_vid = self.to_region_vid(r); // The challenge if this. We have some region variable `r` @@ -1289,7 +1289,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { where T: TypeFoldable<'tcx>, { - tcx.fold_regions(value, &mut false, |r, _db| { + tcx.fold_regions(value, |r, _db| { let vid = self.to_region_vid(r); let scc = self.constraint_sccs.scc(vid); let repr = self.scc_representatives[scc]; diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 81073758791..d182c0cf4e8 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -59,7 +59,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { debug!(?concrete_type, ?substs); let mut subst_regions = vec![self.universal_regions.fr_static]; - let universal_substs = infcx.tcx.fold_regions(substs, &mut false, |region, _| { + let universal_substs = infcx.tcx.fold_regions(substs, |region, _| { if let ty::RePlaceholder(..) = region.kind() { // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs. return region; @@ -91,7 +91,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { subst_regions.dedup(); let universal_concrete_type = - infcx.tcx.fold_regions(concrete_type, &mut false, |region, _| match *region { + infcx.tcx.fold_regions(concrete_type, |region, _| match *region { ty::ReVar(vid) => subst_regions .iter() .find(|ur_vid| self.eval_equal(vid, **ur_vid)) @@ -146,7 +146,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { where T: TypeFoldable<'tcx>, { - tcx.fold_regions(ty, &mut false, |region, _| match *region { + tcx.fold_regions(ty, |region, _| match *region { ty::ReVar(vid) => { // Find something that we can name let upper_bound = self.approx_universal_upper_bound(vid); diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index 2876d60527f..7a8ce621c5d 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -31,7 +31,7 @@ pub fn renumber_regions<'tcx, T>(infcx: &InferCtxt<'_, 'tcx>, value: T) -> T where T: TypeFoldable<'tcx>, { - infcx.tcx.fold_regions(value, &mut false, |_region, _depth| { + infcx.tcx.fold_regions(value, |_region, _depth| { let origin = NllRegionVariableOrigin::Existential { from_forall: false }; infcx.next_nll_region_var(origin) }) diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 3c9e3870aea..5e33d9d25c2 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -23,7 +23,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> { tcx: TyCtxt<'tcx>, universal_regions: &'a UniversalRegions<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, - implicit_region_bound: Option<ty::Region<'tcx>>, + implicit_region_bound: ty::Region<'tcx>, param_env: ty::ParamEnv<'tcx>, locations: Locations, span: Span, @@ -36,7 +36,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, universal_regions: &'a UniversalRegions<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, - implicit_region_bound: Option<ty::Region<'tcx>>, + implicit_region_bound: ty::Region<'tcx>, param_env: ty::ParamEnv<'tcx>, locations: Locations, span: Span, @@ -108,7 +108,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { // create new region variables, which can't be done later when // verifying these bounds. if t1.has_placeholders() { - t1 = tcx.fold_regions(t1, &mut false, |r, _| match *r { + t1 = tcx.fold_regions(t1, |r, _| match *r { ty::RePlaceholder(placeholder) => { self.constraints.placeholder_region(self.infcx, placeholder) } @@ -120,7 +120,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { &mut *self, tcx, region_bound_pairs, - implicit_region_bound, + Some(implicit_region_bound), param_env, ) .type_must_outlive(origin, t1, r2); diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 813307356c4..421ef5be812 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -61,7 +61,7 @@ pub(crate) struct CreateResult<'tcx> { pub(crate) fn create<'tcx>( infcx: &InferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, - implicit_region_bound: Option<ty::Region<'tcx>>, + implicit_region_bound: ty::Region<'tcx>, universal_regions: &Rc<UniversalRegions<'tcx>>, constraints: &mut MirTypeckRegionConstraints<'tcx>, ) -> CreateResult<'tcx> { @@ -223,7 +223,7 @@ struct UniversalRegionRelationsBuilder<'this, 'tcx> { infcx: &'this InferCtxt<'this, 'tcx>, param_env: ty::ParamEnv<'tcx>, universal_regions: Rc<UniversalRegions<'tcx>>, - implicit_region_bound: Option<ty::Region<'tcx>>, + implicit_region_bound: ty::Region<'tcx>, constraints: &'this mut MirTypeckRegionConstraints<'tcx>, // outputs: diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 2259a59e195..2a6ca5246da 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -230,7 +230,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.infcx, &self.borrowck_context.universal_regions, &self.region_bound_pairs, - Some(self.implicit_region_bound), + self.implicit_region_bound, self.param_env, Locations::All(DUMMY_SP), DUMMY_SP, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 355254fe942..542fc6b0f48 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -157,7 +157,7 @@ pub(crate) fn type_check<'mir, 'tcx>( } = free_region_relations::create( infcx, param_env, - Some(implicit_region_bound), + implicit_region_bound, universal_regions, &mut constraints, ); @@ -1142,7 +1142,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.infcx, self.borrowck_context.universal_regions, self.region_bound_pairs, - Some(self.implicit_region_bound), + self.implicit_region_bound, self.param_env, locations, locations.span(self.body), diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index c2c093f9f2f..89d84fcf09c 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -725,7 +725,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { where T: TypeFoldable<'tcx>, { - self.tcx.fold_regions(value, &mut false, |_region, _depth| self.next_nll_region_var(origin)) + self.tcx.fold_regions(value, |_region, _depth| self.next_nll_region_var(origin)) } #[instrument(level = "debug", skip(self, indices))] @@ -817,9 +817,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> { where T: TypeFoldable<'tcx>, { - tcx.fold_regions(value, &mut false, |region, _| { - tcx.mk_region(ty::ReVar(self.to_region_vid(region))) - }) + tcx.fold_regions(value, |region, _| tcx.mk_region(ty::ReVar(self.to_region_vid(region)))) } } diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index cad30181212..9e50d33486c 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -1,11 +1,10 @@ -use crate::assert::expr_if_not; use rustc_ast::{ attr, ptr::P, token, tokenstream::{DelimSpan, TokenStream, TokenTree}, - BorrowKind, Expr, ExprKind, ItemKind, MacArgs, MacCall, MacDelimiter, Mutability, Path, - PathSegment, Stmt, StructRest, UseTree, UseTreeKind, DUMMY_NODE_ID, + BinOpKind, BorrowKind, Expr, ExprKind, ItemKind, MacArgs, MacCall, MacDelimiter, Mutability, + Path, PathSegment, Stmt, StructRest, UnOp, UseTree, UseTreeKind, DUMMY_NODE_ID, }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; @@ -16,11 +15,19 @@ use rustc_span::{ }; pub(super) struct Context<'cx, 'a> { + // An optimization. + // + // Elements that aren't consumed (PartialEq, PartialOrd, ...) can be copied **after** the + // `assert!` expression fails rather than copied on-the-fly. + best_case_captures: Vec<Stmt>, // Top-level `let captureN = Capture::new()` statements capture_decls: Vec<Capture>, cx: &'cx ExtCtxt<'a>, // Formatting string used for debugging fmt_string: String, + // If the current expression being visited consumes itself. Used to construct + // `best_case_captures`. + is_consumed: bool, // Top-level `let __local_bindN = &expr` statements local_bind_decls: Vec<Stmt>, // Used to avoid capturing duplicated paths @@ -36,9 +43,11 @@ pub(super) struct Context<'cx, 'a> { impl<'cx, 'a> Context<'cx, 'a> { pub(super) fn new(cx: &'cx ExtCtxt<'a>, span: Span) -> Self { Self { + best_case_captures: <_>::default(), capture_decls: <_>::default(), cx, fmt_string: <_>::default(), + is_consumed: true, local_bind_decls: <_>::default(), paths: <_>::default(), span, @@ -69,14 +78,22 @@ impl<'cx, 'a> Context<'cx, 'a> { self.manage_cond_expr(&mut cond_expr); let initial_imports = self.build_initial_imports(); let panic = self.build_panic(&expr_str, panic_path); + let cond_expr_with_unlikely = self.build_unlikely(cond_expr); + + let Self { best_case_captures, capture_decls, cx, local_bind_decls, span, .. } = self; - let Self { capture_decls, cx, local_bind_decls, span, .. } = self; + let mut assert_then_stmts = Vec::with_capacity(2); + assert_then_stmts.extend(best_case_captures); + assert_then_stmts.push(self.cx.stmt_expr(panic)); + let assert_then = self.cx.block(span, assert_then_stmts); let mut stmts = Vec::with_capacity(4); stmts.push(initial_imports); stmts.extend(capture_decls.into_iter().map(|c| c.decl)); stmts.extend(local_bind_decls); - stmts.push(cx.stmt_expr(expr_if_not(cx, span, cond_expr, panic, None))); + stmts.push( + cx.stmt_expr(cx.expr(span, ExprKind::If(cond_expr_with_unlikely, assert_then, None))), + ); cx.expr_block(cx.block(span, stmts)) } @@ -115,6 +132,16 @@ impl<'cx, 'a> Context<'cx, 'a> { ) } + /// Takes the conditional expression of `assert!` and then wraps it inside `unlikely` + fn build_unlikely(&self, cond_expr: P<Expr>) -> P<Expr> { + let unlikely_path = self.cx.std_path(&[sym::intrinsics, sym::unlikely]); + self.cx.expr_call( + self.span, + self.cx.expr_path(self.cx.path(self.span, unlikely_path)), + vec![self.cx.expr(self.span, ExprKind::Unary(UnOp::Not, cond_expr))], + ) + } + /// The necessary custom `panic!(...)` expression. /// /// panic!( @@ -167,17 +194,39 @@ impl<'cx, 'a> Context<'cx, 'a> { /// See [Self::manage_initial_capture] and [Self::manage_try_capture] fn manage_cond_expr(&mut self, expr: &mut P<Expr>) { match (*expr).kind { - ExprKind::AddrOf(_, _, ref mut local_expr) => { - self.manage_cond_expr(local_expr); + ExprKind::AddrOf(_, mutability, ref mut local_expr) => { + self.with_is_consumed_management( + matches!(mutability, Mutability::Mut), + |this| this.manage_cond_expr(local_expr) + ); } ExprKind::Array(ref mut local_exprs) => { for local_expr in local_exprs { self.manage_cond_expr(local_expr); } } - ExprKind::Binary(_, ref mut lhs, ref mut rhs) => { - self.manage_cond_expr(lhs); - self.manage_cond_expr(rhs); + ExprKind::Binary(ref op, ref mut lhs, ref mut rhs) => { + self.with_is_consumed_management( + matches!( + op.node, + BinOpKind::Add + | BinOpKind::And + | BinOpKind::BitAnd + | BinOpKind::BitOr + | BinOpKind::BitXor + | BinOpKind::Div + | BinOpKind::Mul + | BinOpKind::Or + | BinOpKind::Rem + | BinOpKind::Shl + | BinOpKind::Shr + | BinOpKind::Sub + ), + |this| { + this.manage_cond_expr(lhs); + this.manage_cond_expr(rhs); + } + ); } ExprKind::Call(_, ref mut local_exprs) => { for local_expr in local_exprs { @@ -228,8 +277,11 @@ impl<'cx, 'a> Context<'cx, 'a> { self.manage_cond_expr(local_expr); } } - ExprKind::Unary(_, ref mut local_expr) => { - self.manage_cond_expr(local_expr); + ExprKind::Unary(un_op, ref mut local_expr) => { + self.with_is_consumed_management( + matches!(un_op, UnOp::Neg | UnOp::Not), + |this| this.manage_cond_expr(local_expr) + ); } // Expressions that are not worth or can not be captured. // @@ -337,9 +389,23 @@ impl<'cx, 'a> Context<'cx, 'a> { )) .add_trailing_semicolon(); let local_bind_path = self.cx.expr_path(Path::from_ident(local_bind)); - let ret = self.cx.stmt_expr(local_bind_path); - let block = self.cx.expr_block(self.cx.block(self.span, vec![try_capture_call, ret])); - *expr = self.cx.expr_deref(self.span, block); + let rslt = if self.is_consumed { + let ret = self.cx.stmt_expr(local_bind_path); + self.cx.expr_block(self.cx.block(self.span, vec![try_capture_call, ret])) + } else { + self.best_case_captures.push(try_capture_call); + local_bind_path + }; + *expr = self.cx.expr_deref(self.span, rslt); + } + + // Calls `f` with the internal `is_consumed` set to `curr_is_consumed` and then + // sets the internal `is_consumed` back to its original value. + fn with_is_consumed_management(&mut self, curr_is_consumed: bool, f: impl FnOnce(&mut Self)) { + let prev_is_consumed = self.is_consumed; + self.is_consumed = curr_is_consumed; + f(self); + self.is_consumed = prev_is_consumed; } } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index d46f2f38d3a..d5e68dbd5b7 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -56,15 +56,14 @@ impl<T: fmt::Display> fmt::Display for MemoryKind<T> { } } -/// Used by `get_size_and_align` to indicate whether the allocation needs to be live. -#[derive(Debug, Copy, Clone)] -pub enum AllocCheck { - /// Allocation must be live and not a function pointer. - Dereferenceable, - /// Allocations needs to be live, but may be a function pointer. - Live, - /// Allocation may be dead. - MaybeDead, +/// The return value of `get_alloc_info` indicates the "kind" of the allocation. +pub enum AllocKind { + /// A regular live data allocation. + LiveData, + /// A function allocation (that fn ptrs point to). + Function, + /// A dead allocation. + Dead, } /// The value of a function pointer. @@ -360,8 +359,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { align, CheckInAllocMsg::MemoryAccessTest, |alloc_id, offset, tag| { - let (size, align) = - self.get_alloc_size_and_align(alloc_id, AllocCheck::Dereferenceable)?; + let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?; Ok((size, align, (alloc_id, offset, tag))) }, ) @@ -379,15 +377,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { msg: CheckInAllocMsg, ) -> InterpResult<'tcx> { self.check_and_deref_ptr(ptr, size, Some(align), msg, |alloc_id, _, _| { - let check = match msg { - CheckInAllocMsg::DerefTest | CheckInAllocMsg::MemoryAccessTest => { - AllocCheck::Dereferenceable - } - CheckInAllocMsg::PointerArithmeticTest - | CheckInAllocMsg::OffsetFromTest - | CheckInAllocMsg::InboundsTest => AllocCheck::Live, - }; - let (size, align) = self.get_alloc_size_and_align(alloc_id, check)?; + let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?; Ok((size, align, ())) })?; Ok(()) @@ -655,30 +645,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Obtain the size and alignment of an allocation, even if that allocation has /// been deallocated. - /// - /// If `liveness` is `AllocCheck::MaybeDead`, this function always returns `Ok`. - pub fn get_alloc_size_and_align( - &self, - id: AllocId, - liveness: AllocCheck, - ) -> InterpResult<'tcx, (Size, Align)> { + pub fn get_alloc_info(&self, id: AllocId) -> (Size, Align, AllocKind) { // # Regular allocations // Don't use `self.get_raw` here as that will // a) cause cycles in case `id` refers to a static // b) duplicate a global's allocation in miri if let Some((_, alloc)) = self.memory.alloc_map.get(id) { - return Ok((alloc.size(), alloc.align)); + return (alloc.size(), alloc.align, AllocKind::LiveData); } // # Function pointers // (both global from `alloc_map` and local from `extra_fn_ptr_map`) if self.get_fn_alloc(id).is_some() { - return if let AllocCheck::Dereferenceable = liveness { - // The caller requested no function pointers. - throw_ub!(DerefFunctionPointer(id)) - } else { - Ok((Size::ZERO, Align::ONE)) - }; + return (Size::ZERO, Align::ONE, AllocKind::Function); } // # Statics @@ -690,32 +669,38 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Use size and align of the type. let ty = self.tcx.type_of(did); let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); - Ok((layout.size, layout.align.abi)) + (layout.size, layout.align.abi, AllocKind::LiveData) } Some(GlobalAlloc::Memory(alloc)) => { // Need to duplicate the logic here, because the global allocations have // different associated types than the interpreter-local ones. let alloc = alloc.inner(); - Ok((alloc.size(), alloc.align)) + (alloc.size(), alloc.align, AllocKind::LiveData) } Some(GlobalAlloc::Function(_)) => bug!("We already checked function pointers above"), // The rest must be dead. None => { - if let AllocCheck::MaybeDead = liveness { - // Deallocated pointers are allowed, we should be able to find - // them in the map. - Ok(*self - .memory - .dead_alloc_map - .get(&id) - .expect("deallocated pointers should all be recorded in `dead_alloc_map`")) - } else { - throw_ub!(PointerUseAfterFree(id)) - } + // Deallocated pointers are allowed, we should be able to find + // them in the map. + let (size, align) = *self + .memory + .dead_alloc_map + .get(&id) + .expect("deallocated pointers should all be recorded in `dead_alloc_map`"); + (size, align, AllocKind::Dead) } } } + /// Obtain the size and alignment of a live allocation. + pub fn get_live_alloc_size_and_align(&self, id: AllocId) -> InterpResult<'tcx, (Size, Align)> { + let (size, align, kind) = self.get_alloc_info(id); + if matches!(kind, AllocKind::Dead) { + throw_ub!(PointerUseAfterFree(id)) + } + Ok((size, align)) + } + fn get_fn_alloc(&self, id: AllocId) -> Option<FnVal<'tcx, M::ExtraFnVal>> { if let Some(extra) = self.memory.extra_fn_ptr_map.get(&id) { Some(FnVal::Other(*extra)) @@ -1187,9 +1172,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let ptr = self.scalar_to_ptr(scalar)?; match self.ptr_try_get_alloc_id(ptr) { Ok((alloc_id, offset, _)) => { - let (size, _align) = self - .get_alloc_size_and_align(alloc_id, AllocCheck::MaybeDead) - .expect("alloc info with MaybeDead cannot fail"); + let (size, _align, _kind) = self.get_alloc_info(alloc_id); // If the pointer is out-of-bounds, it may be null. // Note that one-past-the-end (offset == size) is still inbounds, and never null. offset > size diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index 2b73ad568e0..92f0a7498e3 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -23,7 +23,7 @@ pub use self::eval_context::{ }; pub use self::intern::{intern_const_alloc_recursive, InternKind}; pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump}; -pub use self::memory::{AllocCheck, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind}; +pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind}; pub use self::operand::{ImmTy, Immediate, OpTy, Operand}; pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy}; pub use self::validity::{CtfeValidationMode, RefTracking}; diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index 88ff33b4d09..d8b26f9840b 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -826,6 +826,24 @@ cfg_if! { } } } + } else if #[cfg(target_os = "macos")] { + pub fn get_resident_set_size() -> Option<usize> { + use libc::{c_int, c_void, getpid, proc_pidinfo, proc_taskinfo, PROC_PIDTASKINFO}; + use std::mem; + const PROC_TASKINFO_SIZE: c_int = mem::size_of::<proc_taskinfo>() as c_int; + + unsafe { + let mut info: proc_taskinfo = mem::zeroed(); + let info_ptr = &mut info as *mut proc_taskinfo as *mut c_void; + let pid = getpid() as c_int; + let ret = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, info_ptr, PROC_TASKINFO_SIZE); + if ret == PROC_TASKINFO_SIZE { + Some(info.pti_resident_size as usize) + } else { + None + } + } + } } else if #[cfg(unix)] { pub fn get_resident_set_size() -> Option<usize> { let field = 1; diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index feb82cb0938..4437c0b1b69 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -21,6 +21,7 @@ use crate::owning_ref::{Erased, OwningRef}; use std::collections::HashMap; use std::hash::{BuildHasher, Hash}; use std::ops::{Deref, DerefMut}; +use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe}; pub use std::sync::atomic::Ordering; pub use std::sync::atomic::Ordering::SeqCst; @@ -41,7 +42,6 @@ cfg_if! { } use std::ops::Add; - use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe}; /// This is a single threaded variant of `AtomicU64`, `AtomicUsize`, etc. /// It has explicit ordering arguments and is only intended for use with @@ -339,7 +339,10 @@ cfg_if! { t: T, for_each: impl Fn(T::Item) + Sync + Send, ) { - t.into_par_iter().for_each(for_each) + let ps: Vec<_> = t.into_par_iter().map(|i| catch_unwind(AssertUnwindSafe(|| for_each(i)))).collect(); + ps.into_iter().for_each(|p| if let Err(panic) = p { + resume_unwind(panic) + }); } pub type MetadataRef = OwningRef<Box<dyn Erased + Send + Sync>, [u8]>; diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index caa92e74808..3096af90d47 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -932,7 +932,7 @@ fn describe_codegen_flags() { print_flag_list("-C", config::CG_OPTIONS); } -fn print_flag_list<T>( +pub fn print_flag_list<T>( cmdline_opt: &str, flag_list: &[(&'static str, T, &'static str, &'static str)], ) { diff --git a/compiler/rustc_error_messages/locales/en-US/privacy.ftl b/compiler/rustc_error_messages/locales/en-US/privacy.ftl new file mode 100644 index 00000000000..2b0778f48ca --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/privacy.ftl @@ -0,0 +1,12 @@ +privacy-field-is-private = field `{$field_name}` of {$variant_descr} `{$def_path_str}` is private +privacy-field-is-private-is-update-syntax-label = field `{$field_name}` is private +privacy-field-is-private-label = private field + +privacy-item-is-private = {$kind} `{$descr}` is private + .label = private {$kind} +privacy-unnamed-item-is-private = {$kind} is private + .label = private {$kind} + +privacy-in-public-interface = {$vis_descr} {$kind} `{$descr}` in public interface + .label = can't leak {$vis_descr} {$kind} + .visibility-label = `{$descr}` declared as {$vis_descr} diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 673e160cc1e..90eb5ef5446 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -32,6 +32,7 @@ pub use unic_langid::{langid, LanguageIdentifier}; // Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module. fluent_messages! { parser => "../locales/en-US/parser.ftl", + privacy => "../locales/en-US/privacy.ftl", typeck => "../locales/en-US/typeck.ftl", builtin_macros => "../locales/en-US/builtin_macros.ftl", } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index a4cbc73978d..8b2a995f1c5 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -656,11 +656,6 @@ impl Emitter for SilentEmitter { } } -/// Maximum number of lines we will print for a multiline suggestion; arbitrary. -/// -/// This should be replaced with a more involved mechanism to output multiline suggestions that -/// more closely mimics the regular diagnostic output, where irrelevant code lines are elided. -pub const MAX_SUGGESTION_HIGHLIGHT_LINES: usize = 6; /// Maximum number of suggestions to be shown /// /// Arbitrary, but taken from trait import suggestion limit diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 245719bff12..1e57d66dd9f 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1077,6 +1077,7 @@ impl<'a> ExtCtxt<'a> { self.current_expansion.id.expansion_cause() } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_span_err<S: Into<MultiSpan>>( &self, sp: S, @@ -1101,9 +1102,11 @@ impl<'a> ExtCtxt<'a> { /// /// Compilation will be stopped in the near future (at the end of /// the macro expansion phase). + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { self.sess.parse_sess.span_diagnostic.span_err(sp, msg); } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { self.sess.parse_sess.span_diagnostic.span_warn(sp, msg); } diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 86ff110eec1..c18147592dc 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -9,6 +9,7 @@ #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] #![feature(proc_macro_span)] +#![feature(rustc_attrs)] #![feature(try_blocks)] #![recursion_limit = "256"] diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index e68274e2ad9..384a0f9c225 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -65,7 +65,6 @@ //! example generator inference, and possibly also HIR borrowck. use crate::hir::*; -use crate::itemlikevisit::ParItemLikeVisitor; use rustc_ast::walk_list; use rustc_ast::{Attribute, Label}; use rustc_span::symbol::{Ident, Symbol}; @@ -76,29 +75,6 @@ pub trait IntoVisitor<'hir> { fn into_visitor(&self) -> Self::Visitor; } -pub struct ParDeepVisitor<V>(pub V); - -impl<'hir, V> ParItemLikeVisitor<'hir> for ParDeepVisitor<V> -where - V: IntoVisitor<'hir>, -{ - fn visit_item(&self, item: &'hir Item<'hir>) { - self.0.into_visitor().visit_item(item); - } - - fn visit_trait_item(&self, trait_item: &'hir TraitItem<'hir>) { - self.0.into_visitor().visit_trait_item(trait_item); - } - - fn visit_impl_item(&self, impl_item: &'hir ImplItem<'hir>) { - self.0.into_visitor().visit_impl_item(impl_item); - } - - fn visit_foreign_item(&self, foreign_item: &'hir ForeignItem<'hir>) { - self.0.into_visitor().visit_foreign_item(foreign_item); - } -} - #[derive(Copy, Clone, Debug)] pub enum FnKind<'a> { /// `#[xxx] pub async/const/extern "Abi" fn foo()` diff --git a/compiler/rustc_hir/src/itemlikevisit.rs b/compiler/rustc_hir/src/itemlikevisit.rs deleted file mode 100644 index a490268dc9f..00000000000 --- a/compiler/rustc_hir/src/itemlikevisit.rs +++ /dev/null @@ -1,9 +0,0 @@ -use super::{ForeignItem, ImplItem, Item, TraitItem}; - -/// A parallel variant of `ItemLikeVisitor`. -pub trait ParItemLikeVisitor<'hir> { - fn visit_item(&self, item: &'hir Item<'hir>); - fn visit_trait_item(&self, trait_item: &'hir TraitItem<'hir>); - fn visit_impl_item(&self, impl_item: &'hir ImplItem<'hir>); - fn visit_foreign_item(&self, foreign_item: &'hir ForeignItem<'hir>); -} diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index d845c433d8c..9f32a7da159 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -27,7 +27,6 @@ pub use rustc_span::def_id; mod hir; pub mod hir_id; pub mod intravisit; -pub mod itemlikevisit; pub mod lang_items; pub mod pat_util; mod stable_hash_impls; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index b9596cd10ed..42d52446ab6 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -79,7 +79,7 @@ pub fn find_param_with_region<'tcx>( // May return None; sometimes the tables are not yet populated. let ty = fn_sig.inputs()[index]; let mut found_anon_region = false; - let new_param_ty = tcx.fold_regions(ty, &mut false, |r, _| { + let new_param_ty = tcx.fold_regions(ty, |r, _| { if r == anon_region { found_anon_region = true; replace_region diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 455de47acef..68c709a2e24 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -868,7 +868,7 @@ impl<'tcx> LexicalRegionResolutions<'tcx> { where T: TypeFoldable<'tcx>, { - tcx.fold_regions(value, &mut false, |r, _db| match *r { + tcx.fold_regions(value, |r, _db| match *r { ty::ReVar(rid) => self.resolve_var(rid), _ => r, }) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 7684d861f3c..ebb8d443421 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -39,21 +39,19 @@ pub struct OpaqueTypeDecl<'tcx> { } impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - /// This is a backwards compatibility hack to prevent breaking changes from - /// lazy TAIT around RPIT handling. - pub fn replace_opaque_types_with_inference_vars<T: TypeFoldable<'tcx>>( + pub fn replace_opaque_types_with_inference_vars( &self, - value: T, + ty: Ty<'tcx>, body_id: HirId, span: Span, code: ObligationCauseCode<'tcx>, param_env: ty::ParamEnv<'tcx>, - ) -> InferOk<'tcx, T> { - if !value.has_opaque_types() { - return InferOk { value, obligations: vec![] }; + ) -> InferOk<'tcx, Ty<'tcx>> { + if !ty.has_opaque_types() { + return InferOk { value: ty, obligations: vec![] }; } let mut obligations = vec![]; - let value = value.fold_with(&mut ty::fold::BottomUpFolder { + let value = ty.fold_with(&mut ty::fold::BottomUpFolder { tcx: self.tcx, lt_op: |lt| lt, ct_op: |ct| ct, diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index a268493b28f..1c1906f3375 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -141,9 +141,6 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// `('a, K)` in this list tells us that the bounds in scope /// indicate that `K: 'a`, where `K` is either a generic /// parameter like `T` or a projection like `T::Item`. - /// - `implicit_region_bound`: if some, this is a region bound - /// that is considered to hold for all type parameters (the - /// function body). /// - `param_env` is the parameter environment for the enclosing function. /// - `body_id` is the body-id whose region obligations are being /// processed. @@ -151,7 +148,6 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { pub fn process_registered_region_obligations( &self, region_bound_pairs_map: &FxHashMap<hir::HirId, RegionBoundPairs<'tcx>>, - implicit_region_bound: Option<ty::Region<'tcx>>, param_env: ty::ParamEnv<'tcx>, ) { assert!( @@ -170,13 +166,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let sup_type = self.resolve_vars_if_possible(sup_type); if let Some(region_bound_pairs) = region_bound_pairs_map.get(&body_id) { - let outlives = &mut TypeOutlives::new( - self, - self.tcx, - ®ion_bound_pairs, - implicit_region_bound, - param_env, - ); + let outlives = + &mut TypeOutlives::new(self, self.tcx, ®ion_bound_pairs, None, param_env); outlives.type_must_outlive(origin, sup_type, sub_region); } else { self.tcx.sess.delay_span_bug( diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 191f5f18ec2..86b025dce5e 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -16,6 +16,11 @@ use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt}; pub struct VerifyBoundCx<'cx, 'tcx> { tcx: TyCtxt<'tcx>, region_bound_pairs: &'cx RegionBoundPairs<'tcx>, + /// During borrowck, if there are no outlives bounds on a generic + /// parameter `T`, we assume that `T: 'in_fn_body` holds. + /// + /// Outside of borrowck the only way to prove `T: '?0` is by + /// setting `'?0` to `'empty`. implicit_region_bound: Option<ty::Region<'tcx>>, param_env: ty::ParamEnv<'tcx>, } @@ -263,8 +268,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // fn foo<'a, A>(x: &'a A) { x.bar() } // // The problem is that the type of `x` is `&'a A`. To be - // well-formed, then, A must be lower-generic by `'a`, but we - // don't know that this holds from first principles. + // well-formed, then, A must outlive `'a`, but we don't know that + // this holds from first principles. let from_region_bound_pairs = self.region_bound_pairs.iter().filter_map(|&(r, p)| { debug!( "declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {:?}", diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index fadb1c87933..56c8635a189 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -406,9 +406,12 @@ impl LateLintPass<'_> for Diagnostics { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { let Some((span, def_id, substs)) = typeck_results_of_method_fn(cx, expr) else { return }; debug!(?span, ?def_id, ?substs); - if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs) && - !cx.tcx.has_attr(instance.def_id(), sym::rustc_lint_diagnostics) - { + let has_attr = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs) + .ok() + .and_then(|inst| inst) + .map(|inst| cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics)) + .unwrap_or(false); + if !has_attr { return; } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 2a2dc6822ce..5579e4d19cf 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -4,7 +4,6 @@ use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::def_id::DefId; use rustc_hir::{is_range_literal, Expr, ExprKind, Node}; use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton}; use rustc_middle::ty::subst::SubstsRef; @@ -1483,39 +1482,32 @@ impl InvalidAtomicOrdering { None } - fn matches_ordering(cx: &LateContext<'_>, did: DefId, orderings: &[Symbol]) -> bool { + fn match_ordering(cx: &LateContext<'_>, ord_arg: &Expr<'_>) -> Option<Symbol> { + let ExprKind::Path(ref ord_qpath) = ord_arg.kind else { return None }; + let did = cx.qpath_res(ord_qpath, ord_arg.hir_id).opt_def_id()?; let tcx = cx.tcx; let atomic_ordering = tcx.get_diagnostic_item(sym::Ordering); - orderings.iter().any(|ordering| { - tcx.item_name(did) == *ordering && { - let parent = tcx.parent(did); - Some(parent) == atomic_ordering - // needed in case this is a ctor, not a variant - || tcx.opt_parent(parent) == atomic_ordering - } - }) - } - - fn opt_ordering_defid(cx: &LateContext<'_>, ord_arg: &Expr<'_>) -> Option<DefId> { - if let ExprKind::Path(ref ord_qpath) = ord_arg.kind { - cx.qpath_res(ord_qpath, ord_arg.hir_id).opt_def_id() - } else { - None - } + let name = tcx.item_name(did); + let parent = tcx.parent(did); + [sym::Relaxed, sym::Release, sym::Acquire, sym::AcqRel, sym::SeqCst].into_iter().find( + |&ordering| { + name == ordering + && (Some(parent) == atomic_ordering + // needed in case this is a ctor, not a variant + || tcx.opt_parent(parent) == atomic_ordering) + }, + ) } fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) { - use rustc_hir::def::{DefKind, Res}; - use rustc_hir::QPath; if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::load, sym::store]) && let Some((ordering_arg, invalid_ordering)) = match method { sym::load => Some((&args[1], sym::Release)), sym::store => Some((&args[2], sym::Acquire)), _ => None, } - && let ExprKind::Path(QPath::Resolved(_, path)) = ordering_arg.kind - && let Res::Def(DefKind::Ctor(..), ctor_id) = path.res - && Self::matches_ordering(cx, ctor_id, &[invalid_ordering, sym::AcqRel]) + && let Some(ordering) = Self::match_ordering(cx, ordering_arg) + && (ordering == invalid_ordering || ordering == sym::AcqRel) { cx.struct_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, |diag| { if method == sym::load { @@ -1537,9 +1529,7 @@ impl InvalidAtomicOrdering { && let ExprKind::Path(ref func_qpath) = func.kind && let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id() && matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::fence | sym::compiler_fence)) - && let ExprKind::Path(ref ordering_qpath) = &args[0].kind - && let Some(ordering_def_id) = cx.qpath_res(ordering_qpath, args[0].hir_id).opt_def_id() - && Self::matches_ordering(cx, ordering_def_id, &[sym::Relaxed]) + && Self::match_ordering(cx, &args[0]) == Some(sym::Relaxed) { cx.struct_span_lint(INVALID_ATOMIC_ORDERING, args[0].span, |diag| { diag.build("memory fences cannot have `Relaxed` ordering") @@ -1550,62 +1540,56 @@ impl InvalidAtomicOrdering { } fn check_atomic_compare_exchange(cx: &LateContext<'_>, expr: &Expr<'_>) { - if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::fetch_update, sym::compare_exchange, sym::compare_exchange_weak]) - && let Some((success_order_arg, failure_order_arg)) = match method { - sym::fetch_update => Some((&args[1], &args[2])), - sym::compare_exchange | sym::compare_exchange_weak => Some((&args[3], &args[4])), - _ => None, - } - && let Some(fail_ordering_def_id) = Self::opt_ordering_defid(cx, failure_order_arg) - { - // Helper type holding on to some checking and error reporting data. Has - // - (success ordering, - // - list of failure orderings forbidden by the success order, - // - suggestion message) - type OrdLintInfo = (Symbol, &'static [Symbol], &'static str); - const RELAXED: OrdLintInfo = (sym::Relaxed, &[sym::SeqCst, sym::Acquire], "ordering mode `Relaxed`"); - const ACQUIRE: OrdLintInfo = (sym::Acquire, &[sym::SeqCst], "ordering modes `Acquire` or `Relaxed`"); - const SEQ_CST: OrdLintInfo = (sym::SeqCst, &[], "ordering modes `Acquire`, `SeqCst` or `Relaxed`"); - const RELEASE: OrdLintInfo = (sym::Release, RELAXED.1, RELAXED.2); - const ACQREL: OrdLintInfo = (sym::AcqRel, ACQUIRE.1, ACQUIRE.2); - const SEARCH: [OrdLintInfo; 5] = [RELAXED, ACQUIRE, SEQ_CST, RELEASE, ACQREL]; - - let success_lint_info = Self::opt_ordering_defid(cx, success_order_arg) - .and_then(|success_ord_def_id| -> Option<OrdLintInfo> { - SEARCH - .iter() - .copied() - .find(|(ordering, ..)| { - Self::matches_ordering(cx, success_ord_def_id, &[*ordering]) - }) - }); - if Self::matches_ordering(cx, fail_ordering_def_id, &[sym::Release, sym::AcqRel]) { - // If we don't know the success order is, use what we'd suggest - // if it were maximally permissive. - let suggested = success_lint_info.unwrap_or(SEQ_CST).2; - cx.struct_span_lint(INVALID_ATOMIC_ORDERING, failure_order_arg.span, |diag| { - let msg = format!( - "{}'s failure ordering may not be `Release` or `AcqRel`", - method, - ); - diag.build(&msg) - .help(&format!("consider using {} instead", suggested)) - .emit(); - }); - } else if let Some((success_ord, bad_ords_given_success, suggested)) = success_lint_info { - if Self::matches_ordering(cx, fail_ordering_def_id, bad_ords_given_success) { - cx.struct_span_lint(INVALID_ATOMIC_ORDERING, failure_order_arg.span, |diag| { - let msg = format!( - "{}'s failure ordering may not be stronger than the success ordering of `{}`", - method, - success_ord, - ); - diag.build(&msg) - .help(&format!("consider using {} instead", suggested)) - .emit(); - }); - } - } + let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::fetch_update, sym::compare_exchange, sym::compare_exchange_weak]) + else {return }; + + let (success_order_arg, fail_order_arg) = match method { + sym::fetch_update => (&args[1], &args[2]), + sym::compare_exchange | sym::compare_exchange_weak => (&args[3], &args[4]), + _ => return, + }; + + let Some(fail_ordering) = Self::match_ordering(cx, fail_order_arg) else { return }; + + if matches!(fail_ordering, sym::Release | sym::AcqRel) { + cx.struct_span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg.span, |diag| { + diag.build(&format!( + "`{method}`'s failure ordering may not be `Release` or `AcqRel`, \ + since a failed `{method}` does not result in a write", + )) + .span_label(fail_order_arg.span, "invalid failure ordering") + .help("consider using `Acquire` or `Relaxed` failure ordering instead") + .emit(); + }); + } + + let Some(success_ordering) = Self::match_ordering(cx, success_order_arg) else { return }; + + if matches!( + (success_ordering, fail_ordering), + (sym::Relaxed | sym::Release, sym::Acquire) + | (sym::Relaxed | sym::Release | sym::Acquire | sym::AcqRel, sym::SeqCst) + ) { + let success_suggestion = + if success_ordering == sym::Release && fail_ordering == sym::Acquire { + sym::AcqRel + } else { + fail_ordering + }; + cx.struct_span_lint(INVALID_ATOMIC_ORDERING, success_order_arg.span, |diag| { + diag.build(&format!( + "`{method}`'s success ordering must be at least as strong as its failure ordering" + )) + .span_label(fail_order_arg.span, format!("`{fail_ordering}` failure ordering")) + .span_label(success_order_arg.span, format!("`{success_ordering}` success ordering")) + .span_suggestion_short( + success_order_arg.span, + format!("consider using `{success_suggestion}` success ordering instead"), + format!("std::sync::atomic::Ordering::{success_suggestion}"), + Applicability::MaybeIncorrect, + ) + .emit(); + }); } } } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 738d47ba296..a27b8470e95 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -612,23 +612,6 @@ impl<'hir> Map<'hir> { } } - /// A parallel version of `visit_all_item_likes`. - pub fn par_visit_all_item_likes<V>(self, visitor: &V) - where - V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send, - { - let krate = self.krate(); - par_for_each_in(&krate.owners.raw, |owner| match owner.map(OwnerInfo::node) { - MaybeOwner::Owner(OwnerNode::Item(item)) => visitor.visit_item(item), - MaybeOwner::Owner(OwnerNode::ForeignItem(item)) => visitor.visit_foreign_item(item), - MaybeOwner::Owner(OwnerNode::ImplItem(item)) => visitor.visit_impl_item(item), - MaybeOwner::Owner(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item), - MaybeOwner::Owner(OwnerNode::Crate(_)) - | MaybeOwner::NonOwner(_) - | MaybeOwner::Phantom => {} - }) - } - /// If you don't care about nesting, you should use the /// `tcx.hir_module_items()` query or `module_items()` instead. /// Please see notes in `deep_visit_all_item_likes`. @@ -867,6 +850,10 @@ impl<'hir> Map<'hir> { ) } + pub fn expect_owner(self, id: LocalDefId) -> OwnerNode<'hir> { + self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)).node + } + pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> { match self.tcx.hir_owner(id) { Some(Owner { node: OwnerNode::Item(item), .. }) => item, diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 09b142e0c41..8622a620721 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -10,6 +10,7 @@ use crate::ty::query::Providers; use crate::ty::{DefIdTree, ImplSubject, TyCtxt}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::sync::{par_for_each_in, Send, Sync}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::*; use rustc_query_system::ich::StableHashingContext; @@ -61,6 +62,22 @@ impl ModuleItems { pub fn foreign_items(&self) -> impl Iterator<Item = ForeignItemId> + '_ { self.foreign_items.iter().copied() } + + pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) { + par_for_each_in(&self.items[..], |&id| f(id)) + } + + pub fn par_trait_items(&self, f: impl Fn(TraitItemId) + Send + Sync) { + par_for_each_in(&self.trait_items[..], |&id| f(id)) + } + + pub fn par_impl_items(&self, f: impl Fn(ImplItemId) + Send + Sync) { + par_for_each_in(&self.impl_items[..], |&id| f(id)) + } + + pub fn par_foreign_items(&self, f: impl Fn(ForeignItemId) + Send + Sync) { + par_for_each_in(&self.foreign_items[..], |&id| f(id)) + } } impl<'tcx> TyCtxt<'tcx> { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ca2c03cb614..2e68fc8a7c0 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -826,6 +826,10 @@ rustc_queries! { desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) } } + query check_mod_type_wf(key: LocalDefId) -> () { + desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) } + } + query collect_mod_item_types(key: LocalDefId) -> () { desc { |tcx| "collecting item types in {}", describe_as_module(key, tcx) } } @@ -906,9 +910,10 @@ rustc_queries! { /// Checks whether all impls in the crate pass the overlap check, returning /// which impls fail it. If all impls are correct, the returned slice is empty. - query orphan_check_crate(_: ()) -> &'tcx [LocalDefId] { - desc { - "checking whether the immpl in the this crate follow the orphan rules", + query orphan_check_impl(key: LocalDefId) -> Result<(), ErrorGuaranteed> { + desc { |tcx| + "checking whether impl `{}` follows the orphan rules", + tcx.def_path_str(key.to_def_id()), } } @@ -1398,13 +1403,7 @@ rustc_queries! { separate_provide_extern } - query check_item_well_formed(key: LocalDefId) -> () { - desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key.to_def_id()) } - } - query check_trait_item_well_formed(key: LocalDefId) -> () { - desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key.to_def_id()) } - } - query check_impl_item_well_formed(key: LocalDefId) -> () { + query check_well_formed(key: LocalDefId) -> () { desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key.to_def_id()) } } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 5258d37a14c..ed8de24a65e 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -406,7 +406,7 @@ pub enum ObligationCauseCode<'tcx> { QuestionMark, /// Well-formed checking. If a `WellFormedLoc` is provided, - /// then it will be used to eprform HIR-based wf checking + /// then it will be used to perform HIR-based wf checking /// after an error occurs, in order to generate a more precise error span. /// This is purely for diagnostic purposes - it is always /// correct to use `MiscObligation` instead, or to specify @@ -863,7 +863,7 @@ pub enum ObjectSafetyViolation { impl ObjectSafetyViolation { pub fn error_msg(&self) -> Cow<'static, str> { - match *self { + match self { ObjectSafetyViolation::SizedSelf(_) => "it requires `Self: Sized`".into(), ObjectSafetyViolation::SupertraitSelf(ref spans) => { if spans.iter().any(|sp| *sp != DUMMY_SP) { @@ -873,7 +873,7 @@ impl ObjectSafetyViolation { .into() } } - ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_, _, _), _) => { + ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => { format!("associated function `{}` has no `self` parameter", name).into() } ObjectSafetyViolation::Method( @@ -897,9 +897,11 @@ impl ObjectSafetyViolation { ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) => { format!("method `{}` has generic type parameters", name).into() } - ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) => { - format!("method `{}`'s `self` parameter cannot be dispatched on", name).into() - } + ObjectSafetyViolation::Method( + name, + MethodViolationCode::UndispatchableReceiver(_), + _, + ) => format!("method `{}`'s `self` parameter cannot be dispatched on", name).into(), ObjectSafetyViolation::AssocConst(name, DUMMY_SP) => { format!("it contains associated `const` `{}`", name).into() } @@ -911,51 +913,40 @@ impl ObjectSafetyViolation { } pub fn solution(&self, err: &mut Diagnostic) { - match *self { + match self { ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf(_) => {} ObjectSafetyViolation::Method( name, - MethodViolationCode::StaticMethod(sugg, self_span, has_args), + MethodViolationCode::StaticMethod(Some((add_self_sugg, make_sized_sugg))), _, ) => { err.span_suggestion( - self_span, - &format!( + add_self_sugg.1, + format!( "consider turning `{}` into a method by giving it a `&self` argument", name ), - format!("&self{}", if has_args { ", " } else { "" }), + add_self_sugg.0.to_string(), + Applicability::MaybeIncorrect, + ); + err.span_suggestion( + make_sized_sugg.1, + format!( + "alternatively, consider constraining `{}` so it does not apply to \ + trait objects", + name + ), + make_sized_sugg.0.to_string(), Applicability::MaybeIncorrect, ); - match sugg { - Some((sugg, span)) => { - err.span_suggestion( - span, - &format!( - "alternatively, consider constraining `{}` so it does not apply to \ - trait objects", - name - ), - sugg, - Applicability::MaybeIncorrect, - ); - } - None => { - err.help(&format!( - "consider turning `{}` into a method by giving it a `&self` \ - argument or constraining it so it does not apply to trait objects", - name - )); - } - } } ObjectSafetyViolation::Method( name, - MethodViolationCode::UndispatchableReceiver, - span, + MethodViolationCode::UndispatchableReceiver(Some(span)), + _, ) => { err.span_suggestion( - span, + *span, &format!( "consider changing method `{}`'s `self` parameter to be `&self`", name @@ -991,13 +982,13 @@ impl ObjectSafetyViolation { } /// Reasons a method might not be object-safe. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)] pub enum MethodViolationCode { /// e.g., `fn foo()` - StaticMethod(Option<(&'static str, Span)>, Span, bool /* has args */), + StaticMethod(Option<(/* add &self */ (String, Span), /* add Self: Sized */ (String, Span))>), /// e.g., `fn foo(&self, x: Self)` - ReferencesSelfInput(usize), + ReferencesSelfInput(Option<Span>), /// e.g., `fn foo(&self) -> Self` ReferencesSelfOutput, @@ -1009,7 +1000,7 @@ pub enum MethodViolationCode { Generic, /// the method's receiver (`self` argument) can't be dispatched on - UndispatchableReceiver, + UndispatchableReceiver(Option<Span>), } /// These are the error cases for `codegen_fulfill_obligation`. diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index b1b8bc13e2f..a6310ae5e66 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -465,13 +465,12 @@ impl<'tcx> TyCtxt<'tcx> { pub fn fold_regions<T>( self, value: T, - skipped_regions: &mut bool, mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>, ) -> T where T: TypeFoldable<'tcx>, { - value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f)) + value.fold_with(&mut RegionFolder::new(self, &mut f)) } /// Invoke `callback` on every region appearing free in `value`. @@ -579,7 +578,6 @@ impl<'tcx> TyCtxt<'tcx> { pub struct RegionFolder<'a, 'tcx> { tcx: TyCtxt<'tcx>, - skipped_regions: &'a mut bool, /// Stores the index of a binder *just outside* the stuff we have /// visited. So this begins as INNERMOST; when we pass through a @@ -597,10 +595,9 @@ impl<'a, 'tcx> RegionFolder<'a, 'tcx> { #[inline] pub fn new( tcx: TyCtxt<'tcx>, - skipped_regions: &'a mut bool, fold_region_fn: &'a mut dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>, ) -> RegionFolder<'a, 'tcx> { - RegionFolder { tcx, skipped_regions, current_index: ty::INNERMOST, fold_region_fn } + RegionFolder { tcx, current_index: ty::INNERMOST, fold_region_fn } } } @@ -624,7 +621,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { match *r { ty::ReLateBound(debruijn, _) if debruijn < self.current_index => { debug!(?self.current_index, "skipped bound region"); - *self.skipped_regions = true; r } _ => { diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index f3bdd63ee6d..113af328a91 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -6,6 +6,7 @@ #![feature(let_chains)] #![feature(let_else)] #![feature(never_type)] +#![feature(rustc_attrs)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 58d5d43cfbf..0869ed65ad2 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -357,6 +357,7 @@ impl<'a> DerefMut for SnapshotParser<'a> { } impl<'a> Parser<'a> { + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub(super) fn span_err<S: Into<MultiSpan>>( &self, sp: S, @@ -365,6 +366,7 @@ impl<'a> Parser<'a> { err.span_err(sp, self.diagnostic()) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_span_err<S: Into<MultiSpan>>( &self, sp: S, diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index d952e288a64..5785921fb1e 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -4,14 +4,15 @@ version = "0.0.0" edition = "2021" [dependencies] -rustc_middle = { path = "../rustc_middle" } rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } +rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } -rustc_typeck = { path = "../rustc_typeck" } +rustc_macros = { path = "../rustc_macros" } +rustc_middle = { path = "../rustc_middle" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -rustc_data_structures = { path = "../rustc_data_structures" } rustc_trait_selection = { path = "../rustc_trait_selection" } +rustc_typeck = { path = "../rustc_typeck" } tracing = "0.1" diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs new file mode 100644 index 00000000000..482721d373a --- /dev/null +++ b/compiler/rustc_privacy/src/errors.rs @@ -0,0 +1,75 @@ +use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; +use rustc_span::{Span, Symbol}; + +#[derive(SessionDiagnostic)] +#[error(privacy::field_is_private, code = "E0451")] +pub struct FieldIsPrivate { + #[primary_span] + pub span: Span, + pub field_name: Symbol, + pub variant_descr: &'static str, + pub def_path_str: String, + #[subdiagnostic] + pub label: FieldIsPrivateLabel, +} + +#[derive(SessionSubdiagnostic)] +pub enum FieldIsPrivateLabel { + #[label(privacy::field_is_private_is_update_syntax_label)] + IsUpdateSyntax { + #[primary_span] + span: Span, + field_name: Symbol, + }, + #[label(privacy::field_is_private_label)] + Other { + #[primary_span] + span: Span, + }, +} + +#[derive(SessionDiagnostic)] +#[error(privacy::item_is_private)] +pub struct ItemIsPrivate<'a> { + #[primary_span] + #[label] + pub span: Span, + pub kind: &'a str, + pub descr: String, +} + +#[derive(SessionDiagnostic)] +#[error(privacy::unnamed_item_is_private)] +pub struct UnnamedItemIsPrivate { + #[primary_span] + pub span: Span, + pub kind: &'static str, +} + +// Duplicate of `InPublicInterface` but with a different error code, shares the same slug. +#[derive(SessionDiagnostic)] +#[error(privacy::in_public_interface, code = "E0445")] +pub struct InPublicInterfaceTraits<'a> { + #[primary_span] + #[label] + pub span: Span, + pub vis_descr: &'static str, + pub kind: &'a str, + pub descr: String, + #[label(privacy::visibility_label)] + pub vis_span: Span, +} + +// Duplicate of `InPublicInterfaceTraits` but with a different error code, shares the same slug. +#[derive(SessionDiagnostic)] +#[error(privacy::in_public_interface, code = "E0446")] +pub struct InPublicInterface<'a> { + #[primary_span] + #[label] + pub span: Span, + pub vis_descr: &'static str, + pub kind: &'a str, + pub descr: String, + #[label(privacy::visibility_label)] + pub vis_span: Span, +} diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index b27c986d0f9..238c917bbc3 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1,15 +1,19 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(associated_type_defaults)] #![feature(control_flow_enum)] +#![feature(rustc_private)] #![feature(try_blocks)] -#![feature(associated_type_defaults)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] +#![cfg_attr(not(bootstrap), deny(rustc::untranslatable_diagnostic))] +#![cfg_attr(not(bootstrap), deny(rustc::diagnostic_outside_of_impl))] + +mod errors; use rustc_ast::MacroDef; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::intern::Interned; -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID}; @@ -34,6 +38,11 @@ use std::marker::PhantomData; use std::ops::ControlFlow; use std::{cmp, fmt, mem}; +use errors::{ + FieldIsPrivate, FieldIsPrivateLabel, InPublicInterface, InPublicInterfaceTraits, ItemIsPrivate, + UnnamedItemIsPrivate, +}; + //////////////////////////////////////////////////////////////////////////////// /// Generic infrastructure used to implement specific visitors below. //////////////////////////////////////////////////////////////////////////////// @@ -935,23 +944,17 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { let hir_id = self.tcx.hir().local_def_id_to_hir_id(self.current_item); let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id).1; if !field.vis.is_accessible_from(def_id, self.tcx) { - let label = if in_update_syntax { - format!("field `{}` is private", field.name) - } else { - "private field".to_string() - }; - - struct_span_err!( - self.tcx.sess, + self.tcx.sess.emit_err(FieldIsPrivate { span, - E0451, - "field `{}` of {} `{}` is private", - field.name, - def.variant_descr(), - self.tcx.def_path_str(def.did()) - ) - .span_label(span, label) - .emit(); + field_name: field.name, + variant_descr: def.variant_descr(), + def_path_str: self.tcx.def_path_str(def.did()), + label: if in_update_syntax { + FieldIsPrivateLabel::IsUpdateSyntax { span, field_name: field.name } + } else { + FieldIsPrivateLabel::Other { span } + }, + }); } } } @@ -1075,11 +1078,11 @@ impl<'tcx> TypePrivacyVisitor<'tcx> { fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { let is_error = !self.item_is_accessible(def_id); if is_error { - self.tcx - .sess - .struct_span_err(self.span, &format!("{} `{}` is private", kind, descr)) - .span_label(self.span, &format!("private {}", kind)) - .emit(); + self.tcx.sess.emit_err(ItemIsPrivate { + span: self.span, + kind, + descr: descr.to_string(), + }); } is_error } @@ -1250,13 +1253,10 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()), }; let kind = kind.descr(def_id); - let msg = match name { - Some(name) => format!("{} `{}` is private", kind, name), - None => format!("{} is private", kind), + let _ = match name { + Some(name) => sess.emit_err(ItemIsPrivate { span, kind, descr: name }), + None => sess.emit_err(UnnamedItemIsPrivate { span, kind }), }; - sess.struct_span_err(span, &msg) - .span_label(span, &format!("private {}", kind)) - .emit(); return; } } @@ -1753,22 +1753,31 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { } } }; - let make_msg = || format!("{} {} `{}` in public interface", vis_descr, kind, descr); let span = self.tcx.def_span(self.item_def_id.to_def_id()); if self.has_old_errors || self.in_assoc_ty || self.tcx.resolutions(()).has_pub_restricted { - let mut err = if kind == "trait" { - struct_span_err!(self.tcx.sess, span, E0445, "{}", make_msg()) - } else { - struct_span_err!(self.tcx.sess, span, E0446, "{}", make_msg()) - }; + let descr = descr.to_string(); let vis_span = self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id)); - err.span_label(span, format!("can't leak {} {}", vis_descr, kind)); - err.span_label(vis_span, format!("`{}` declared as {}", descr, vis_descr)); - err.emit(); + if kind == "trait" { + self.tcx.sess.emit_err(InPublicInterfaceTraits { + span, + vis_descr, + kind, + descr, + vis_span, + }); + } else { + self.tcx.sess.emit_err(InPublicInterface { + span, + vis_descr, + kind, + descr, + vis_span, + }); + } } else { let err_code = if kind == "trait" { "E0445" } else { "E0446" }; self.tcx.struct_span_lint_hir( @@ -1776,7 +1785,12 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { hir_id, span, |lint| { - lint.build(&format!("{} (error {})", make_msg(), err_code)).emit(); + lint.build(&format!( + "{} (error {})", + format!("{} {} `{}` in public interface", vis_descr, kind, descr), + err_code + )) + .emit(); }, ); } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index f1814eebfa6..b5058fd699a 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -280,6 +280,7 @@ impl Session { self.crate_types.set(crate_types).expect("`crate_types` was initialized twice") } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_span_warn<S: Into<MultiSpan>>( &self, sp: S, @@ -287,6 +288,7 @@ impl Session { ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_span_warn(sp, msg) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_span_warn_with_expectation<S: Into<MultiSpan>>( &self, sp: S, @@ -295,6 +297,7 @@ impl Session { ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_span_warn_with_expectation(sp, msg, id) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_span_warn_with_code<S: Into<MultiSpan>>( &self, sp: S, @@ -303,9 +306,11 @@ impl Session { ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_span_warn_with_code(sp, msg, code) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_warn(msg) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_warn_with_expectation( &self, msg: impl Into<DiagnosticMessage>, @@ -313,6 +318,7 @@ impl Session { ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_warn_with_expectation(msg, id) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_span_allow<S: Into<MultiSpan>>( &self, sp: S, @@ -320,9 +326,11 @@ impl Session { ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_span_allow(sp, msg) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_allow(msg) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_expect( &self, msg: impl Into<DiagnosticMessage>, @@ -330,6 +338,7 @@ impl Session { ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_expect(msg, id) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_span_err<S: Into<MultiSpan>>( &self, sp: S, @@ -337,6 +346,7 @@ impl Session { ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { self.diagnostic().struct_span_err(sp, msg) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_span_err_with_code<S: Into<MultiSpan>>( &self, sp: S, @@ -346,12 +356,14 @@ impl Session { self.diagnostic().struct_span_err_with_code(sp, msg, code) } // FIXME: This method should be removed (every error should have an associated error code). + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_err( &self, msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { self.parse_sess.struct_err(msg) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_err_with_code( &self, msg: impl Into<DiagnosticMessage>, @@ -359,6 +371,7 @@ impl Session { ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { self.diagnostic().struct_err_with_code(msg, code) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_warn_with_code( &self, msg: impl Into<DiagnosticMessage>, @@ -366,6 +379,7 @@ impl Session { ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_warn_with_code(msg, code) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_span_fatal<S: Into<MultiSpan>>( &self, sp: S, @@ -373,6 +387,7 @@ impl Session { ) -> DiagnosticBuilder<'_, !> { self.diagnostic().struct_span_fatal(sp, msg) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>( &self, sp: S, @@ -381,13 +396,16 @@ impl Session { ) -> DiagnosticBuilder<'_, !> { self.diagnostic().struct_span_fatal_with_code(sp, msg, code) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> { self.diagnostic().struct_fatal(msg) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! { self.diagnostic().span_fatal(sp, msg) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn span_fatal_with_code<S: Into<MultiSpan>>( &self, sp: S, @@ -396,9 +414,11 @@ impl Session { ) -> ! { self.diagnostic().span_fatal_with_code(sp, msg, code) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn fatal(&self, msg: impl Into<DiagnosticMessage>) -> ! { self.diagnostic().fatal(msg).raise() } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn span_err_or_warn<S: Into<MultiSpan>>( &self, is_warning: bool, @@ -411,6 +431,7 @@ impl Session { self.span_err(sp, msg); } } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn span_err<S: Into<MultiSpan>>( &self, sp: S, @@ -418,6 +439,7 @@ impl Session { ) -> ErrorGuaranteed { self.diagnostic().span_err(sp, msg) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn span_err_with_code<S: Into<MultiSpan>>( &self, sp: S, @@ -426,6 +448,7 @@ impl Session { ) { self.diagnostic().span_err_with_code(sp, msg, code) } + #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed { self.diagnostic().err(msg) } diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index a8ddcc9bfac..59dbea70534 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -8,6 +8,7 @@ //! LLVM. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(assert_matches)] #![feature(associated_type_bounds)] #![feature(exhaustive_patterns)] #![feature(let_else)] diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs index 86f76fdb6a7..9d36e37d7b8 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs @@ -8,7 +8,7 @@ pub fn target() -> Target { // FIXME: The leak sanitizer currently fails the tests, see #88132. base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD; - base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".into(), "arm64".into()]); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-arch", "arm64"]); base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove()); // Clang automatically chooses a more specific target based on diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs index 965b254c289..162b091b269 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs @@ -2,20 +2,13 @@ // uefi-base module for generic UEFI options. use super::uefi_msvc_base; -use crate::spec::{LinkerFlavor, LldFlavor, Target}; +use crate::spec::{LinkerFlavor, Target}; pub fn target() -> Target { let mut base = uefi_msvc_base::opts(); base.max_atomic_width = Some(64); - - let pre_link_args_msvc = vec!["/machine:arm64".into()]; - - base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().extend(pre_link_args_msvc.clone()); - base.pre_link_args - .get_mut(&LinkerFlavor::Lld(LldFlavor::Link)) - .unwrap() - .extend(pre_link_args_msvc); + base.add_pre_link_args(LinkerFlavor::Msvc, &["/machine:arm64"]); Target { llvm_target: "aarch64-unknown-windows".into(), diff --git a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs index 67df73fa935..8c2a9bcfde6 100644 --- a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs +++ b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs @@ -1,19 +1,13 @@ -use crate::spec::{cvs, LinkArgs, LinkerFlavor, RelocModel, Target, TargetOptions}; +use crate::spec::{cvs, LinkerFlavor, RelocModel, Target, TargetOptions}; /// A base target for Nintendo 3DS devices using the devkitARM toolchain. /// /// Requires the devkitARM toolchain for 3DS targets on the host system. pub fn target() -> Target { - let mut pre_link_args = LinkArgs::new(); - pre_link_args.insert( + let pre_link_args = TargetOptions::link_args( LinkerFlavor::Gcc, - vec![ - "-specs=3dsx.specs".into(), - "-mtune=mpcore".into(), - "-mfloat-abi=hard".into(), - "-mtp=soft".into(), - ], + &["-specs=3dsx.specs", "-mtune=mpcore", "-mfloat-abi=hard", "-mtp=soft"], ); Target { diff --git a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs b/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs index 2afd93fcad8..38c117a495e 100644 --- a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs @@ -10,7 +10,7 @@ use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::android_base::opts(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-march=armv7-a"]); Target { llvm_target: "armv7-none-linux-android".into(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs b/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs index 269bf8b8bcd..b4cf2c5ee22 100644 --- a/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs @@ -2,10 +2,6 @@ use super::{wasm32_unknown_emscripten, LinkerFlavor, Target}; pub fn target() -> Target { let mut target = wasm32_unknown_emscripten::target(); - target.post_link_args.entry(LinkerFlavor::Em).or_default().extend(vec![ - "-sWASM=0".into(), - "--memory-init-file".into(), - "0".into(), - ]); + target.add_post_link_args(LinkerFlavor::Em, &["-sWASM=0", "--memory-init-file", "0"]); target } diff --git a/compiler/rustc_target/src/spec/avr_gnu_base.rs b/compiler/rustc_target/src/spec/avr_gnu_base.rs index c288e8b0e9e..4fd6c06394d 100644 --- a/compiler/rustc_target/src/spec/avr_gnu_base.rs +++ b/compiler/rustc_target/src/spec/avr_gnu_base.rs @@ -3,7 +3,8 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; /// A base target for AVR devices using the GNU toolchain. /// /// Requires GNU avr-gcc and avr-binutils on the host system. -pub fn target(target_cpu: &'static str) -> Target { +/// FIXME: Remove the second parameter when const string concatenation is possible. +pub fn target(target_cpu: &'static str, mmcu: &'static str) -> Target { Target { arch: "avr".into(), data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(), @@ -17,10 +18,8 @@ pub fn target(target_cpu: &'static str) -> Target { linker: Some("avr-gcc".into()), executables: true, eh_frame_header: false, - pre_link_args: [(LinkerFlavor::Gcc, vec![format!("-mmcu={}", target_cpu).into()])] - .into_iter() - .collect(), - late_link_args: [(LinkerFlavor::Gcc, vec!["-lgcc".into()])].into_iter().collect(), + pre_link_args: TargetOptions::link_args(LinkerFlavor::Gcc, &[mmcu]), + late_link_args: TargetOptions::link_args(LinkerFlavor::Gcc, &["-lgcc"]), max_atomic_width: Some(0), atomic_cas: false, ..TargetOptions::default() diff --git a/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs b/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs index 6871ca0f789..6c16b03cc28 100644 --- a/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs +++ b/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs @@ -1,5 +1,5 @@ use crate::spec::Target; pub fn target() -> Target { - super::avr_gnu_base::target("atmega328") + super::avr_gnu_base::target("atmega328", "-mmcu=atmega328") } diff --git a/compiler/rustc_target/src/spec/fuchsia_base.rs b/compiler/rustc_target/src/spec/fuchsia_base.rs index b64875e32bd..b02b70f76ee 100644 --- a/compiler/rustc_target/src/spec/fuchsia_base.rs +++ b/compiler/rustc_target/src/spec/fuchsia_base.rs @@ -1,23 +1,20 @@ -use crate::spec::{ - crt_objects, cvs, LinkArgs, LinkOutputKind, LinkerFlavor, LldFlavor, TargetOptions, -}; +use crate::spec::{crt_objects, cvs, LinkOutputKind, LinkerFlavor, LldFlavor, TargetOptions}; pub fn opts() -> TargetOptions { - let mut pre_link_args = LinkArgs::new(); - pre_link_args.insert( - LinkerFlavor::Lld(LldFlavor::Ld), - vec![ - "--build-id".into(), - "--hash-style=gnu".into(), - "-z".into(), - "max-page-size=4096".into(), - "-z".into(), - "now".into(), - "-z".into(), - "rodynamic".into(), - "-z".into(), - "separate-loadable-segments".into(), - "--pack-dyn-relocs=relr".into(), + let pre_link_args = TargetOptions::link_args( + LinkerFlavor::Ld, + &[ + "--build-id", + "--hash-style=gnu", + "-z", + "max-page-size=4096", + "-z", + "now", + "-z", + "rodynamic", + "-z", + "separate-loadable-segments", + "--pack-dyn-relocs=relr", ], ); diff --git a/compiler/rustc_target/src/spec/hermit_base.rs b/compiler/rustc_target/src/spec/hermit_base.rs index 7cbd42417e6..e43153177f0 100644 --- a/compiler/rustc_target/src/spec/hermit_base.rs +++ b/compiler/rustc_target/src/spec/hermit_base.rs @@ -1,10 +1,9 @@ -use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions, TlsModel}; +use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions, TlsModel}; pub fn opts() -> TargetOptions { - let mut pre_link_args = LinkArgs::new(); - pre_link_args.insert( - LinkerFlavor::Lld(LldFlavor::Ld), - vec!["--build-id".into(), "--hash-style=gnu".into(), "--Bstatic".into()], + let pre_link_args = TargetOptions::link_args( + LinkerFlavor::Ld, + &["--build-id", "--hash-style=gnu", "--Bstatic"], ); TargetOptions { diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/i686_apple_darwin.rs index ad716a6cd5a..1718bd77b86 100644 --- a/compiler/rustc_target/src/spec/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/i686_apple_darwin.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::apple_base::opts("macos"); base.cpu = "yonah".into(); base.max_atomic_width = Some(64); - base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".into()]); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]); base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs index 554b0f34499..6318654399c 100644 --- a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs @@ -1,19 +1,16 @@ -use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, Target}; +use crate::spec::{FramePointer, LinkerFlavor, Target}; pub fn target() -> Target { let mut base = super::windows_gnu_base::opts(); base.cpu = "pentium4".into(); - base.pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".into(), "i386pe".into()]); base.max_atomic_width = Some(64); base.frame_pointer = FramePointer::Always; // Required for backtraces base.linker = Some("i686-w64-mingw32-gcc".into()); // Mark all dynamic libraries and executables as compatible with the larger 4GiB address // space available to x86 Windows binaries on x86_64. - base.pre_link_args - .entry(LinkerFlavor::Gcc) - .or_default() - .push("-Wl,--large-address-aware".into()); + base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pe", "--large-address-aware"]); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-Wl,--large-address-aware"]); Target { llvm_target: "i686-pc-windows-gnu".into(), diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs index fb0cb6a6943..f4ceaa1ca4b 100644 --- a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs @@ -1,24 +1,22 @@ -use crate::spec::{LinkerFlavor, LldFlavor, Target}; +use crate::spec::{LinkerFlavor, Target}; pub fn target() -> Target { let mut base = super::windows_msvc_base::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); - let pre_link_args_msvc = vec![ - // Mark all dynamic libraries and executables as compatible with the larger 4GiB address - // space available to x86 Windows binaries on x86_64. - "/LARGEADDRESSAWARE".into(), - // Ensure the linker will only produce an image if it can also produce a table of - // the image's safe exception handlers. - // https://docs.microsoft.com/en-us/cpp/build/reference/safeseh-image-has-safe-exception-handlers - "/SAFESEH".into(), - ]; - base.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone()); - base.pre_link_args - .entry(LinkerFlavor::Lld(LldFlavor::Link)) - .or_default() - .extend(pre_link_args_msvc); + base.add_pre_link_args( + LinkerFlavor::Msvc, + &[ + // Mark all dynamic libraries and executables as compatible with the larger 4GiB address + // space available to x86 Windows binaries on x86_64. + "/LARGEADDRESSAWARE", + // Ensure the linker will only produce an image if it can also produce a table of + // the image's safe exception handlers. + // https://docs.microsoft.com/en-us/cpp/build/reference/safeseh-image-has-safe-exception-handlers + "/SAFESEH", + ], + ); // Workaround for #95429 base.has_thread_local = false; diff --git a/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs index 9f0cb04c65d..aff284bf2bc 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs @@ -4,9 +4,7 @@ pub fn target() -> Target { let mut base = super::freebsd_base::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); - let pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); - pre_link_args.push("-m32".into()); - pre_link_args.push("-Wl,-znotext".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "-Wl,-znotext"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/i686_unknown_haiku.rs index d1af163f1cf..87aa74e406c 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_haiku.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_haiku.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::haiku_base::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); - base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".into()]); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs index 0998c618f31..765803d1692 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs index a697f292da0..d9492804349 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs @@ -4,8 +4,7 @@ pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into()); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-Wl,-melf_i386".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "-Wl,-melf_i386"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs index 2807d328205..8de698b51f0 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::netbsd_base::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs index 78462eb63b8..7f25a1a16c1 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs @@ -4,8 +4,7 @@ pub fn target() -> Target { let mut base = super::openbsd_base::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into()); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-fuse-ld=lld".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "-fuse-ld=lld"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs index 75f7a2209c8..d52810d2fb0 100644 --- a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs @@ -1,18 +1,15 @@ -use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, Target}; +use crate::spec::{FramePointer, LinkerFlavor, Target}; pub fn target() -> Target { let mut base = super::windows_uwp_gnu_base::opts(); base.cpu = "pentium4".into(); - base.pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".into(), "i386pe".into()]); base.max_atomic_width = Some(64); base.frame_pointer = FramePointer::Always; // Required for backtraces // Mark all dynamic libraries and executables as compatible with the larger 4GiB address // space available to x86 Windows binaries on x86_64. - base.pre_link_args - .entry(LinkerFlavor::Gcc) - .or_default() - .push("-Wl,--large-address-aware".into()); + base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pe", "--large-address-aware"]); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-Wl,--large-address-aware"]); Target { llvm_target: "i686-pc-windows-gnu".into(), diff --git a/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs index d51ed7c1f7a..f62404e8279 100644 --- a/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::vxworks_base::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/illumos_base.rs b/compiler/rustc_target/src/spec/illumos_base.rs index ef8f90a4da8..b0e1b109be1 100644 --- a/compiler/rustc_target/src/spec/illumos_base.rs +++ b/compiler/rustc_target/src/spec/illumos_base.rs @@ -1,10 +1,9 @@ -use crate::spec::{cvs, FramePointer, LinkArgs, LinkerFlavor, TargetOptions}; +use crate::spec::{cvs, FramePointer, LinkerFlavor, TargetOptions}; pub fn opts() -> TargetOptions { - let mut late_link_args = LinkArgs::new(); - late_link_args.insert( + let late_link_args = TargetOptions::link_args( LinkerFlavor::Gcc, - vec![ + &[ // The illumos libc contains a stack unwinding implementation, as // does libgcc_s. The latter implementation includes several // additional symbols that are not always in base libc. To force @@ -15,13 +14,13 @@ pub fn opts() -> TargetOptions { // FIXME: This should be replaced by a more complete and generic // mechanism for controlling the order of library arguments passed // to the linker. - "-lc".into(), + "-lc", // LLVM will insert calls to the stack protector functions // "__stack_chk_fail" and "__stack_chk_guard" into code in native // object files. Some platforms include these symbols directly in // libc, but at least historically these have been provided in // libssp.so on illumos and Solaris systems. - "-lssp".into(), + "-lssp", ], ); diff --git a/compiler/rustc_target/src/spec/mipsel_sony_psp.rs b/compiler/rustc_target/src/spec/mipsel_sony_psp.rs index 03e0934ea5e..e3522de6de0 100644 --- a/compiler/rustc_target/src/spec/mipsel_sony_psp.rs +++ b/compiler/rustc_target/src/spec/mipsel_sony_psp.rs @@ -1,13 +1,11 @@ use crate::spec::{cvs, Target, TargetOptions}; -use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, RelocModel}; +use crate::spec::{LinkerFlavor, LldFlavor, RelocModel}; // The PSP has custom linker requirements. const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld"); pub fn target() -> Target { - let mut pre_link_args = LinkArgs::new(); - pre_link_args - .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["--emit-relocs".into(), "--nmagic".into()]); + let pre_link_args = TargetOptions::link_args(LinkerFlavor::Ld, &["--emit-relocs", "--nmagic"]); Target { llvm_target: "mipsel-sony-psp".into(), diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index da0589cdd20..a08603da040 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1459,6 +1459,44 @@ pub struct TargetOptions { pub supports_stack_protector: bool, } +/// Add arguments for the given flavor and also for its "twin" flavors +/// that have a compatible command line interface. +fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) { + let mut insert = |flavor| { + link_args.entry(flavor).or_default().extend(args.iter().copied().map(Cow::Borrowed)) + }; + insert(flavor); + match flavor { + LinkerFlavor::Ld => insert(LinkerFlavor::Lld(LldFlavor::Ld)), + LinkerFlavor::Msvc => insert(LinkerFlavor::Lld(LldFlavor::Link)), + LinkerFlavor::Lld(LldFlavor::Wasm) => {} + LinkerFlavor::Lld(lld_flavor) => { + panic!("add_link_args: use non-LLD flavor for {:?}", lld_flavor) + } + LinkerFlavor::Gcc + | LinkerFlavor::Em + | LinkerFlavor::L4Bender + | LinkerFlavor::BpfLinker + | LinkerFlavor::PtxLinker => {} + } +} + +impl TargetOptions { + fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs { + let mut link_args = LinkArgs::new(); + add_link_args(&mut link_args, flavor, args); + link_args + } + + fn add_pre_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) { + add_link_args(&mut self.pre_link_args, flavor, args); + } + + fn add_post_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) { + add_link_args(&mut self.post_link_args, flavor, args); + } +} + impl Default for TargetOptions { /// Creates a set of "sane defaults" for any target. This is still /// incomplete, and if used for compilation, will certainly not work. diff --git a/compiler/rustc_target/src/spec/msvc_base.rs b/compiler/rustc_target/src/spec/msvc_base.rs index 00cc9620243..c4df4b546e3 100644 --- a/compiler/rustc_target/src/spec/msvc_base.rs +++ b/compiler/rustc_target/src/spec/msvc_base.rs @@ -1,14 +1,9 @@ -use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, SplitDebuginfo, TargetOptions}; +use crate::spec::{LinkerFlavor, LldFlavor, SplitDebuginfo, TargetOptions}; pub fn opts() -> TargetOptions { - let pre_link_args_msvc = vec![ - // Suppress the verbose logo and authorship debugging output, which would needlessly - // clog any log files. - "/NOLOGO".into(), - ]; - let mut pre_link_args = LinkArgs::new(); - pre_link_args.insert(LinkerFlavor::Msvc, pre_link_args_msvc.clone()); - pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Link), pre_link_args_msvc); + // Suppress the verbose logo and authorship debugging output, which would needlessly + // clog any log files. + let pre_link_args = TargetOptions::link_args(LinkerFlavor::Msvc, &["/NOLOGO"]); TargetOptions { linker_flavor: LinkerFlavor::Msvc, diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs index 595769c4bfa..803453c4ac4 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs @@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::freebsd_base::opts(); base.cpu = "ppc64".into(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs index 24d5d187e1a..5413c4f33ff 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs @@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, RelroLevel, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); base.cpu = "ppc64".into(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.max_atomic_width = Some(64); // ld.so in at least RHEL6 on ppc64 has a bug related to BIND_NOW, so only enable partial RELRO diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs index 0f465ccfe77..159335eb607 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs @@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); base.cpu = "ppc64".into(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs index 491d344aedb..b7420d232ca 100644 --- a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs @@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::vxworks_base::opts(); base.cpu = "ppc64".into(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs index b198e667ccc..a3d18004371 100644 --- a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs @@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::freebsd_base::opts(); base.cpu = "ppc64le".into(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs index 09e3936db26..e18ff3be448 100644 --- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs @@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); base.cpu = "ppc64le".into(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs index 8a947b091cb..b84943d23a9 100644 --- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs @@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); base.cpu = "ppc64le".into(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs index c27b84775df..516b2de37ea 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs @@ -3,12 +3,8 @@ use crate::spec::{LinkerFlavor, RelocModel, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::freebsd_base::opts(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into()); // Extra hint to linker that we are generating secure-PLT code. - base.pre_link_args - .entry(LinkerFlavor::Gcc) - .or_default() - .push("--target=powerpc-unknown-freebsd13.0".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "--target=powerpc-unknown-freebsd13.0"]); base.max_atomic_width = Some(32); Target { diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs index 88f61500e3c..6686a0bbf04 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs @@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]); base.max_atomic_width = Some(32); Target { diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs index 3ee548750b9..6a250f4b51c 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs @@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mspe".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-mspe"]); base.max_atomic_width = Some(32); Target { diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs index ce33c787f33..34200c67906 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs @@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]); base.max_atomic_width = Some(32); Target { diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs index 998225f4dae..60661ef9b5d 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs @@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::netbsd_base::opts(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]); base.max_atomic_width = Some(32); Target { diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs index 76709cec591..3f24966e06e 100644 --- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs @@ -3,8 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::vxworks_base::opts(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into()); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("--secure-plt".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "--secure-plt"]); base.max_atomic_width = Some(32); Target { diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs index 7b5d1242c52..0f04f41f9e5 100644 --- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs +++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs @@ -3,8 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::vxworks_base::opts(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mspe".into()); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("--secure-plt".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-mspe", "--secure-plt"]); base.max_atomic_width = Some(32); Target { diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs index 718303a4b4d..836ab0e3728 100644 --- a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs @@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::netbsd_base::opts(); base.cpu = "v9".into(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs index 2aaa0ca6df8..4a192df392f 100644 --- a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs @@ -5,7 +5,7 @@ pub fn target() -> Target { let mut base = super::openbsd_base::opts(); base.endian = Endian::Big; base.cpu = "v9".into(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs index 71d3de0bfd1..ea4fafa4b06 100644 --- a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs @@ -6,7 +6,7 @@ pub fn target() -> Target { base.endian = Endian::Big; base.cpu = "v9".into(); base.max_atomic_width = Some(64); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mv8plus".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-mv8plus"]); Target { llvm_target: "sparc-unknown-linux-gnu".into(), diff --git a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs index 79ae54aa666..aac09181a74 100644 --- a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs +++ b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs @@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, Target}; pub fn target() -> Target { let mut base = super::solaris_base::opts(); base.endian = Endian::Big; - base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".into()]); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); // llvm calls this "v9" base.cpu = "v9".into(); base.vendor = "sun".into(); diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs index 0865ca7ea7d..c7c5a231901 100644 --- a/compiler/rustc_target/src/spec/tests/tests_impl.rs +++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs @@ -1,4 +1,5 @@ use super::super::*; +use std::assert_matches::assert_matches; // Test target self-consistency and JSON encoding/decoding roundtrip. pub(super) fn test_target(target: Target) { @@ -14,35 +15,105 @@ impl Target { assert_eq!(self.is_like_wasm, self.arch == "wasm32" || self.arch == "wasm64"); assert!(self.is_like_windows || !self.is_like_msvc); - // Check that LLD with the given flavor is treated identically to the linker it emulates. - // If your target really needs to deviate from the rules below, except it and document the - // reasons. - assert_eq!( - self.linker_flavor == LinkerFlavor::Msvc - || self.linker_flavor == LinkerFlavor::Lld(LldFlavor::Link), - self.lld_flavor == LldFlavor::Link, - ); - assert_eq!(self.is_like_msvc, self.lld_flavor == LldFlavor::Link); - for args in &[ + // Check that default linker flavor and lld flavor are compatible + // with some other key properties. + assert_eq!(self.is_like_osx, matches!(self.lld_flavor, LldFlavor::Ld64)); + assert_eq!(self.is_like_msvc, matches!(self.lld_flavor, LldFlavor::Link)); + assert_eq!(self.is_like_wasm, matches!(self.lld_flavor, LldFlavor::Wasm)); + assert_eq!(self.os == "l4re", matches!(self.linker_flavor, LinkerFlavor::L4Bender)); + assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::Em)); + assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::BpfLinker)); + assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::PtxLinker)); + + for args in [ &self.pre_link_args, &self.late_link_args, &self.late_link_args_dynamic, &self.late_link_args_static, &self.post_link_args, ] { + for (&flavor, flavor_args) in args { + assert!(!flavor_args.is_empty()); + // Check that flavors mentioned in link args are compatible with the default flavor. + match (self.linker_flavor, self.lld_flavor) { + ( + LinkerFlavor::Ld | LinkerFlavor::Lld(LldFlavor::Ld) | LinkerFlavor::Gcc, + LldFlavor::Ld, + ) => { + assert_matches!( + flavor, + LinkerFlavor::Ld | LinkerFlavor::Lld(LldFlavor::Ld) | LinkerFlavor::Gcc + ) + } + (LinkerFlavor::Gcc, LldFlavor::Ld64) => { + assert_matches!(flavor, LinkerFlavor::Gcc) + } + (LinkerFlavor::Msvc | LinkerFlavor::Lld(LldFlavor::Link), LldFlavor::Link) => { + assert_matches!( + flavor, + LinkerFlavor::Msvc | LinkerFlavor::Lld(LldFlavor::Link) + ) + } + (LinkerFlavor::Lld(LldFlavor::Wasm) | LinkerFlavor::Gcc, LldFlavor::Wasm) => { + assert_matches!( + flavor, + LinkerFlavor::Lld(LldFlavor::Wasm) | LinkerFlavor::Gcc + ) + } + (LinkerFlavor::L4Bender, LldFlavor::Ld) => { + assert_matches!(flavor, LinkerFlavor::L4Bender) + } + (LinkerFlavor::Em, LldFlavor::Wasm) => { + assert_matches!(flavor, LinkerFlavor::Em) + } + (LinkerFlavor::BpfLinker, LldFlavor::Ld) => { + assert_matches!(flavor, LinkerFlavor::BpfLinker) + } + (LinkerFlavor::PtxLinker, LldFlavor::Ld) => { + assert_matches!(flavor, LinkerFlavor::PtxLinker) + } + flavors => unreachable!("unexpected flavor combination: {:?}", flavors), + } + + // Check that link args for cc and non-cc versions of flavors are consistent. + let check_noncc = |noncc_flavor| { + if let Some(noncc_args) = args.get(&noncc_flavor) { + for arg in flavor_args { + if let Some(suffix) = arg.strip_prefix("-Wl,") { + assert!(noncc_args.iter().any(|a| a == suffix)); + } + } + } + }; + match self.linker_flavor { + LinkerFlavor::Gcc => match self.lld_flavor { + LldFlavor::Ld => { + check_noncc(LinkerFlavor::Ld); + check_noncc(LinkerFlavor::Lld(LldFlavor::Ld)); + } + LldFlavor::Wasm => check_noncc(LinkerFlavor::Lld(LldFlavor::Wasm)), + LldFlavor::Ld64 | LldFlavor::Link => {} + }, + _ => {} + } + } + + // Check that link args for lld and non-lld versions of flavors are consistent. + assert_eq!(args.get(&LinkerFlavor::Ld), args.get(&LinkerFlavor::Lld(LldFlavor::Ld))); assert_eq!( args.get(&LinkerFlavor::Msvc), args.get(&LinkerFlavor::Lld(LldFlavor::Link)), ); - if args.contains_key(&LinkerFlavor::Msvc) { - assert_eq!(self.lld_flavor, LldFlavor::Link); - } } + assert!( (self.pre_link_objects_fallback.is_empty() && self.post_link_objects_fallback.is_empty()) || self.crt_objects_fallback.is_some() ); + + // If your target really needs to deviate from the rules below, + // except it and document the reasons. // Keep the default "unknown" vendor instead. assert_ne!(self.vendor, ""); if !self.can_use_os_unknown() { diff --git a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs index f6cbbd38cf4..4d09d3a4d10 100644 --- a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions}; +use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::windows_msvc_base::opts(); @@ -9,12 +9,7 @@ pub fn target() -> Target { // should be smart enough to insert branch islands only // where necessary, but this is not the observed behavior. // Disabling the LBR optimization works around the issue. - let pre_link_args_msvc = "/OPT:NOLBR"; - base.pre_link_args.entry(LinkerFlavor::Msvc).or_default().push(pre_link_args_msvc.into()); - base.pre_link_args - .entry(LinkerFlavor::Lld(LldFlavor::Link)) - .or_default() - .push(pre_link_args_msvc.into()); + base.add_pre_link_args(LinkerFlavor::Msvc, &["/OPT:NOLBR"]); Target { llvm_target: "thumbv7a-pc-windows-msvc".into(), diff --git a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs index 9a3e8b5c5f8..4cad9e18370 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs @@ -10,7 +10,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::android_base::opts(); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-march=armv7-a"]); Target { llvm_target: "armv7-none-linux-android".into(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/uefi_msvc_base.rs b/compiler/rustc_target/src/spec/uefi_msvc_base.rs index bc7244b3a45..aee8eb2e31c 100644 --- a/compiler/rustc_target/src/spec/uefi_msvc_base.rs +++ b/compiler/rustc_target/src/spec/uefi_msvc_base.rs @@ -14,27 +14,25 @@ use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, StackProbeType, Target pub fn opts() -> TargetOptions { let mut base = super::msvc_base::opts(); - let pre_link_args_msvc = vec![ - // Non-standard subsystems have no default entry-point in PE+ files. We have to define - // one. "efi_main" seems to be a common choice amongst other implementations and the - // spec. - "/entry:efi_main".into(), - // COFF images have a "Subsystem" field in their header, which defines what kind of - // program it is. UEFI has 3 fields reserved, which are EFI_APPLICATION, - // EFI_BOOT_SERVICE_DRIVER, and EFI_RUNTIME_DRIVER. We default to EFI_APPLICATION, - // which is very likely the most common option. Individual projects can override this - // with custom linker flags. - // The subsystem-type only has minor effects on the application. It defines the memory - // regions the application is loaded into (runtime-drivers need to be put into - // reserved areas), as well as whether a return from the entry-point is treated as - // exit (default for applications). - "/subsystem:efi_application".into(), - ]; - base.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone()); - base.pre_link_args - .entry(LinkerFlavor::Lld(LldFlavor::Link)) - .or_default() - .extend(pre_link_args_msvc); + base.add_pre_link_args( + LinkerFlavor::Msvc, + &[ + // Non-standard subsystems have no default entry-point in PE+ files. We have to define + // one. "efi_main" seems to be a common choice amongst other implementations and the + // spec. + "/entry:efi_main", + // COFF images have a "Subsystem" field in their header, which defines what kind of + // program it is. UEFI has 3 fields reserved, which are EFI_APPLICATION, + // EFI_BOOT_SERVICE_DRIVER, and EFI_RUNTIME_DRIVER. We default to EFI_APPLICATION, + // which is very likely the most common option. Individual projects can override this + // with custom linker flags. + // The subsystem-type only has minor effects on the application. It defines the memory + // regions the application is loaded into (runtime-drivers need to be put into + // reserved areas), as well as whether a return from the entry-point is treated as + // exit (default for applications). + "/subsystem:efi_application", + ], + ); TargetOptions { os: "uefi".into(), diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs index 1b94c59b55f..c7e7d221086 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs @@ -2,21 +2,11 @@ use super::{cvs, wasm_base}; use super::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions}; pub fn target() -> Target { - let mut options = wasm_base::options(); - - let clang_args = options.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); - - // Rust really needs a way for users to specify exports and imports in - // the source code. --export-dynamic isn't the right tool for this job, - // however it does have the side effect of automatically exporting a lot - // of symbols, which approximates what people want when compiling for - // wasm32-unknown-unknown expect, so use it for now. - clang_args.push("--export-dynamic".into()); - - let mut post_link_args = LinkArgs::new(); - post_link_args.insert( + // Reset flags for non-Em flavors back to empty to satisfy sanity checking tests. + let pre_link_args = LinkArgs::new(); + let post_link_args = TargetOptions::link_args( LinkerFlavor::Em, - vec!["-sABORTING_MALLOC=0".into(), "-Wl,--fatal-warnings".into()], + &["-sABORTING_MALLOC=0", "-Wl,--fatal-warnings"], ); let opts = TargetOptions { @@ -26,12 +16,13 @@ pub fn target() -> Target { // functionality, and a .wasm file. exe_suffix: ".js".into(), linker: None, + pre_link_args, + post_link_args, relocation_model: RelocModel::Pic, panic_strategy: PanicStrategy::Unwind, no_default_libraries: false, - post_link_args, families: cvs!["unix", "wasm"], - ..options + ..wasm_base::options() }; Target { llvm_target: "wasm32-unknown-emscripten".into(), diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs index 214b5fce5a6..4e2927dd913 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs @@ -29,27 +29,30 @@ pub fn target() -> Target { // code on this target due to this ABI mismatch. options.default_adjusted_cabi = Some(Abi::Wasm); - let clang_args = options.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); - - // Make sure clang uses LLD as its linker and is configured appropriately - // otherwise - clang_args.push("--target=wasm32-unknown-unknown".into()); - - // For now this target just never has an entry symbol no matter the output - // type, so unconditionally pass this. - clang_args.push("-Wl,--no-entry".into()); - - // Rust really needs a way for users to specify exports and imports in - // the source code. --export-dynamic isn't the right tool for this job, - // however it does have the side effect of automatically exporting a lot - // of symbols, which approximates what people want when compiling for - // wasm32-unknown-unknown expect, so use it for now. - clang_args.push("-Wl,--export-dynamic".into()); - - // Add the flags to wasm-ld's args too. - let lld_args = options.pre_link_args.entry(LinkerFlavor::Lld(LldFlavor::Wasm)).or_default(); - lld_args.push("--no-entry".into()); - lld_args.push("--export-dynamic".into()); + options.add_pre_link_args( + LinkerFlavor::Lld(LldFlavor::Wasm), + &[ + // For now this target just never has an entry symbol no matter the output + // type, so unconditionally pass this. + "--no-entry", + // Rust really needs a way for users to specify exports and imports in + // the source code. --export-dynamic isn't the right tool for this job, + // however it does have the side effect of automatically exporting a lot + // of symbols, which approximates what people want when compiling for + // wasm32-unknown-unknown expect, so use it for now. + "--export-dynamic", + ], + ); + options.add_pre_link_args( + LinkerFlavor::Gcc, + &[ + // Make sure clang uses LLD as its linker and is configured appropriately + // otherwise + "--target=wasm32-unknown-unknown", + "-Wl,--no-entry", + "-Wl,--export-dynamic", + ], + ); Target { llvm_target: "wasm32-unknown-unknown".into(), diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs index 10eb78e4e25..280457d68b9 100644 --- a/compiler/rustc_target/src/spec/wasm32_wasi.rs +++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs @@ -80,11 +80,7 @@ pub fn target() -> Target { options.os = "wasi".into(); options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm); - options - .pre_link_args - .entry(LinkerFlavor::Gcc) - .or_insert(Vec::new()) - .push("--target=wasm32-wasi".into()); + options.add_pre_link_args(LinkerFlavor::Gcc, &["--target=wasm32-wasi"]); options.pre_link_objects_fallback = crt_objects::pre_wasi_fallback(); options.post_link_objects_fallback = crt_objects::post_wasi_fallback(); diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs index 6826c0ac62b..5211f7707fb 100644 --- a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs @@ -14,19 +14,25 @@ pub fn target() -> Target { let mut options = wasm_base::options(); options.os = "unknown".into(); options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm); - let clang_args = options.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); - // Make sure clang uses LLD as its linker and is configured appropriately - // otherwise - clang_args.push("--target=wasm64-unknown-unknown".into()); - - // For now this target just never has an entry symbol no matter the output - // type, so unconditionally pass this. - clang_args.push("-Wl,--no-entry".into()); - - let lld_args = options.pre_link_args.get_mut(&LinkerFlavor::Lld(LldFlavor::Wasm)).unwrap(); - lld_args.push("--no-entry".into()); - lld_args.push("-mwasm64".into()); + options.add_pre_link_args( + LinkerFlavor::Lld(LldFlavor::Wasm), + &[ + // For now this target just never has an entry symbol no matter the output + // type, so unconditionally pass this. + "--no-entry", + "-mwasm64", + ], + ); + options.add_pre_link_args( + LinkerFlavor::Gcc, + &[ + // Make sure clang uses LLD as its linker and is configured appropriately + // otherwise + "--target=wasm64-unknown-unknown", + "-Wl,--no-entry", + ], + ); // Any engine that implements wasm64 will surely implement the rest of these // features since they were all merged into the official spec by the time diff --git a/compiler/rustc_target/src/spec/wasm_base.rs b/compiler/rustc_target/src/spec/wasm_base.rs index de7b7374af3..5736402ae14 100644 --- a/compiler/rustc_target/src/spec/wasm_base.rs +++ b/compiler/rustc_target/src/spec/wasm_base.rs @@ -1,63 +1,56 @@ use super::crt_objects::CrtObjectsFallback; use super::{cvs, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel}; -use std::collections::BTreeMap; pub fn options() -> TargetOptions { - let mut lld_args = Vec::new(); - let mut clang_args = Vec::new(); - let mut arg = |arg: &'static str| { - lld_args.push(arg.into()); - clang_args.push(format!("-Wl,{}", arg).into()); - }; - - // By default LLD only gives us one page of stack (64k) which is a - // little small. Default to a larger stack closer to other PC platforms - // (1MB) and users can always inject their own link-args to override this. - arg("-z"); - arg("stack-size=1048576"); - - // By default LLD's memory layout is: - // - // 1. First, a blank page - // 2. Next, all static data - // 3. Finally, the main stack (which grows down) - // - // This has the unfortunate consequence that on stack overflows you - // corrupt static data and can cause some exceedingly weird bugs. To - // help detect this a little sooner we instead request that the stack is - // placed before static data. - // - // This means that we'll generate slightly larger binaries as references - // to static data will take more bytes in the ULEB128 encoding, but - // stack overflow will be guaranteed to trap as it underflows instead of - // corrupting static data. - arg("--stack-first"); - - // FIXME we probably shouldn't pass this but instead pass an explicit list - // of symbols we'll allow to be undefined. We don't currently have a - // mechanism of knowing, however, which symbols are intended to be imported - // from the environment and which are intended to be imported from other - // objects linked elsewhere. This is a coarse approximation but is sure to - // hide some bugs and frustrate someone at some point, so we should ideally - // work towards a world where we can explicitly list symbols that are - // supposed to be imported and have all other symbols generate errors if - // they remain undefined. - arg("--allow-undefined"); - - // Rust code should never have warnings, and warnings are often - // indicative of bugs, let's prevent them. - arg("--fatal-warnings"); - - // LLD only implements C++-like demangling, which doesn't match our own - // mangling scheme. Tell LLD to not demangle anything and leave it up to - // us to demangle these symbols later. Currently rustc does not perform - // further demangling, but tools like twiggy and wasm-bindgen are intended - // to do so. - arg("--no-demangle"); - - let mut pre_link_args = BTreeMap::new(); - pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Wasm), lld_args); - pre_link_args.insert(LinkerFlavor::Gcc, clang_args); + macro_rules! args { + ($prefix:literal) => { + &[ + // By default LLD only gives us one page of stack (64k) which is a + // little small. Default to a larger stack closer to other PC platforms + // (1MB) and users can always inject their own link-args to override this. + concat!($prefix, "-z"), + concat!($prefix, "stack-size=1048576"), + // By default LLD's memory layout is: + // + // 1. First, a blank page + // 2. Next, all static data + // 3. Finally, the main stack (which grows down) + // + // This has the unfortunate consequence that on stack overflows you + // corrupt static data and can cause some exceedingly weird bugs. To + // help detect this a little sooner we instead request that the stack is + // placed before static data. + // + // This means that we'll generate slightly larger binaries as references + // to static data will take more bytes in the ULEB128 encoding, but + // stack overflow will be guaranteed to trap as it underflows instead of + // corrupting static data. + concat!($prefix, "--stack-first"), + // FIXME we probably shouldn't pass this but instead pass an explicit list + // of symbols we'll allow to be undefined. We don't currently have a + // mechanism of knowing, however, which symbols are intended to be imported + // from the environment and which are intended to be imported from other + // objects linked elsewhere. This is a coarse approximation but is sure to + // hide some bugs and frustrate someone at some point, so we should ideally + // work towards a world where we can explicitly list symbols that are + // supposed to be imported and have all other symbols generate errors if + // they remain undefined. + concat!($prefix, "--allow-undefined"), + // Rust code should never have warnings, and warnings are often + // indicative of bugs, let's prevent them. + concat!($prefix, "--fatal-warnings"), + // LLD only implements C++-like demangling, which doesn't match our own + // mangling scheme. Tell LLD to not demangle anything and leave it up to + // us to demangle these symbols later. Currently rustc does not perform + // further demangling, but tools like twiggy and wasm-bindgen are intended + // to do so. + concat!($prefix, "--no-demangle"), + ] + }; + } + + let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::Lld(LldFlavor::Wasm), args!("")); + super::add_link_args(&mut pre_link_args, LinkerFlavor::Gcc, args!("-Wl,")); TargetOptions { is_like_wasm: true, diff --git a/compiler/rustc_target/src/spec/windows_gnu_base.rs b/compiler/rustc_target/src/spec/windows_gnu_base.rs index d11f1f7d3f8..a0480f386f7 100644 --- a/compiler/rustc_target/src/spec/windows_gnu_base.rs +++ b/compiler/rustc_target/src/spec/windows_gnu_base.rs @@ -1,31 +1,35 @@ use crate::spec::crt_objects::{self, CrtObjectsFallback}; -use crate::spec::{cvs, LinkArgs, LinkerFlavor, LldFlavor, TargetOptions}; +use crate::spec::{cvs, LinkerFlavor, TargetOptions}; pub fn opts() -> TargetOptions { - let mut pre_link_args = LinkArgs::new(); - pre_link_args.insert( + let mut pre_link_args = TargetOptions::link_args( + LinkerFlavor::Ld, + &[ + // Enable ASLR + "--dynamicbase", + // ASLR will rebase it anyway so leaving that option enabled only leads to confusion + "--disable-auto-image-base", + ], + ); + super::add_link_args( + &mut pre_link_args, LinkerFlavor::Gcc, - vec![ + &[ // Tell GCC to avoid linker plugins, because we are not bundling // them with Windows installer, and Rust does its own LTO anyways. - "-fno-use-linker-plugin".into(), - // Enable ASLR - "-Wl,--dynamicbase".into(), - // ASLR will rebase it anyway so leaving that option enabled only leads to confusion - "-Wl,--disable-auto-image-base".into(), + "-fno-use-linker-plugin", + "-Wl,--dynamicbase", + "-Wl,--disable-auto-image-base", ], ); - let mut late_link_args = LinkArgs::new(); - let mut late_link_args_dynamic = LinkArgs::new(); - let mut late_link_args_static = LinkArgs::new(); // Order of `late_link_args*` was found through trial and error to work with various // mingw-w64 versions (not tested on the CI). It's expected to change from time to time. - let mingw_libs = vec![ - "-lmsvcrt".into(), - "-lmingwex".into(), - "-lmingw32".into(), - "-lgcc".into(), // alas, mingw* libraries above depend on libgcc + let mingw_libs = &[ + "-lmsvcrt", + "-lmingwex", + "-lmingw32", + "-lgcc", // alas, mingw* libraries above depend on libgcc // mingw's msvcrt is a weird hybrid import library and static library. // And it seems that the linker fails to use import symbols from msvcrt // that are required from functions in msvcrt in certain cases. For example @@ -33,31 +37,27 @@ pub fn opts() -> TargetOptions { // The library is purposely listed twice to fix that. // // See https://github.com/rust-lang/rust/pull/47483 for some more details. - "-lmsvcrt".into(), - "-luser32".into(), - "-lkernel32".into(), - ]; - late_link_args.insert(LinkerFlavor::Gcc, mingw_libs.clone()); - late_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), mingw_libs); - let dynamic_unwind_libs = vec![ - // If any of our crates are dynamically linked then we need to use - // the shared libgcc_s-dw2-1.dll. This is required to support - // unwinding across DLL boundaries. - "-lgcc_s".into(), - ]; - late_link_args_dynamic.insert(LinkerFlavor::Gcc, dynamic_unwind_libs.clone()); - late_link_args_dynamic.insert(LinkerFlavor::Lld(LldFlavor::Ld), dynamic_unwind_libs); - let static_unwind_libs = vec![ - // If all of our crates are statically linked then we can get away - // with statically linking the libgcc unwinding code. This allows - // binaries to be redistributed without the libgcc_s-dw2-1.dll - // dependency, but unfortunately break unwinding across DLL - // boundaries when unwinding across FFI boundaries. - "-lgcc_eh".into(), - "-l:libpthread.a".into(), + "-lmsvcrt", + "-luser32", + "-lkernel32", ]; - late_link_args_static.insert(LinkerFlavor::Gcc, static_unwind_libs.clone()); - late_link_args_static.insert(LinkerFlavor::Lld(LldFlavor::Ld), static_unwind_libs); + let mut late_link_args = TargetOptions::link_args(LinkerFlavor::Ld, mingw_libs); + super::add_link_args(&mut late_link_args, LinkerFlavor::Gcc, mingw_libs); + // If any of our crates are dynamically linked then we need to use + // the shared libgcc_s-dw2-1.dll. This is required to support + // unwinding across DLL boundaries. + let dynamic_unwind_libs = &["-lgcc_s"]; + let mut late_link_args_dynamic = + TargetOptions::link_args(LinkerFlavor::Ld, dynamic_unwind_libs); + super::add_link_args(&mut late_link_args_dynamic, LinkerFlavor::Gcc, dynamic_unwind_libs); + // If all of our crates are statically linked then we can get away + // with statically linking the libgcc unwinding code. This allows + // binaries to be redistributed without the libgcc_s-dw2-1.dll + // dependency, but unfortunately break unwinding across DLL + // boundaries when unwinding across FFI boundaries. + let static_unwind_libs = &["-lgcc_eh", "-l:libpthread.a"]; + let mut late_link_args_static = TargetOptions::link_args(LinkerFlavor::Ld, static_unwind_libs); + super::add_link_args(&mut late_link_args_static, LinkerFlavor::Gcc, static_unwind_libs); TargetOptions { os: "windows".into(), diff --git a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs b/compiler/rustc_target/src/spec/windows_gnullvm_base.rs index 9f9f8be8718..30f995007a9 100644 --- a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs +++ b/compiler/rustc_target/src/spec/windows_gnullvm_base.rs @@ -1,28 +1,17 @@ -use crate::spec::{cvs, LinkArgs, LinkerFlavor, TargetOptions}; +use crate::spec::{cvs, LinkerFlavor, TargetOptions}; pub fn opts() -> TargetOptions { - let pre_link_args = LinkArgs::from([( + // We cannot use `-nodefaultlibs` because compiler-rt has to be passed + // as a path since it's not added to linker search path by the default. + // There were attemts to make it behave like libgcc (so one can just use -l<name>) + // but LLVM maintainers rejected it: https://reviews.llvm.org/D51440 + let pre_link_args = + TargetOptions::link_args(LinkerFlavor::Gcc, &["-nolibc", "--unwindlib=none"]); + // Order of `late_link_args*` does not matter with LLD. + let late_link_args = TargetOptions::link_args( LinkerFlavor::Gcc, - vec![ - // We cannot use `-nodefaultlibs` because compiler-rt has to be passed - // as a path since it's not added to linker search path by the default. - // There were attemts to make it behave like libgcc (so one can just use -l<name>) - // but LLVM maintainers rejected it: https://reviews.llvm.org/D51440 - "-nolibc".into(), - "--unwindlib=none".into(), - ], - )]); - let late_link_args = LinkArgs::from([( - LinkerFlavor::Gcc, - // Order of `late_link_args*` does not matter with LLD. - vec![ - "-lmingw32".into(), - "-lmingwex".into(), - "-lmsvcrt".into(), - "-lkernel32".into(), - "-luser32".into(), - ], - )]); + &["-lmingw32", "-lmingwex", "-lmsvcrt", "-lkernel32", "-luser32"], + ); TargetOptions { os: "windows".into(), diff --git a/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs b/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs index 11968391776..334dec43ef7 100644 --- a/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs +++ b/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs @@ -1,28 +1,25 @@ -use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, TargetOptions}; +use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions}; pub fn opts() -> TargetOptions { let base = super::windows_gnu_base::opts(); // FIXME: This should be updated for the exception machinery changes from #67502 // and inherit from `windows_gnu_base`, at least partially. - let mut late_link_args = LinkArgs::new(); + let mingw_libs = &[ + "-lwinstorecompat", + "-lruntimeobject", + "-lsynchronization", + "-lvcruntime140_app", + "-lucrt", + "-lwindowsapp", + "-lmingwex", + "-lmingw32", + ]; + let mut late_link_args = TargetOptions::link_args(LinkerFlavor::Ld, mingw_libs); + super::add_link_args(&mut late_link_args, LinkerFlavor::Gcc, mingw_libs); + // Reset the flags back to empty until the FIXME above is addressed. let late_link_args_dynamic = LinkArgs::new(); let late_link_args_static = LinkArgs::new(); - let mingw_libs = vec![ - //"-lwinstorecompat".into(), - //"-lmingwex".into(), - //"-lwinstorecompat".into(), - "-lwinstorecompat".into(), - "-lruntimeobject".into(), - "-lsynchronization".into(), - "-lvcruntime140_app".into(), - "-lucrt".into(), - "-lwindowsapp".into(), - "-lmingwex".into(), - "-lmingw32".into(), - ]; - late_link_args.insert(LinkerFlavor::Gcc, mingw_libs.clone()); - late_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), mingw_libs); TargetOptions { abi: "uwp".into(), diff --git a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs b/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs index d6b065b529a..f2573fc2d21 100644 --- a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs +++ b/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs @@ -1,16 +1,11 @@ -use crate::spec::{LinkerFlavor, LldFlavor, TargetOptions}; +use crate::spec::{LinkerFlavor, TargetOptions}; pub fn opts() -> TargetOptions { let mut opts = super::windows_msvc_base::opts(); opts.abi = "uwp".into(); opts.vendor = "uwp".into(); - let pre_link_args_msvc = vec!["/APPCONTAINER".into(), "mincore.lib".into()]; - opts.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone()); - opts.pre_link_args - .entry(LinkerFlavor::Lld(LldFlavor::Link)) - .or_default() - .extend(pre_link_args_msvc); + opts.add_pre_link_args(LinkerFlavor::Msvc, &["/APPCONTAINER", "mincore.lib"]); opts } diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs index 51d14f0403a..dbd26899c18 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs @@ -6,8 +6,7 @@ pub fn target() -> Target { base.cpu = "core2".into(); base.max_atomic_width = Some(128); // core2 support cmpxchg16b base.frame_pointer = FramePointer::Always; - base.pre_link_args - .insert(LinkerFlavor::Gcc, vec!["-m64".into(), "-arch".into(), "x86_64".into()]); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-arch", "x86_64"]); base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs index 47c70513faf..4348d924579 100644 --- a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs +++ b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs @@ -1,41 +1,44 @@ -use std::{borrow::Cow, iter}; +use std::borrow::Cow; use crate::spec::cvs; use super::{LinkerFlavor, LldFlavor, Target, TargetOptions}; pub fn target() -> Target { - const PRE_LINK_ARGS: &[&str] = &[ - "-e", - "elf_entry", - "-Bstatic", - "--gc-sections", - "-z", - "text", - "-z", - "norelro", - "--no-undefined", - "--error-unresolved-symbols", - "--no-undefined-version", - "-Bsymbolic", - "--export-dynamic", - // The following symbols are needed by libunwind, which is linked after - // libstd. Make sure they're included in the link. - "-u", - "__rust_abort", - "-u", - "__rust_c_alloc", - "-u", - "__rust_c_dealloc", - "-u", - "__rust_print_err", - "-u", - "__rust_rwlock_rdlock", - "-u", - "__rust_rwlock_unlock", - "-u", - "__rust_rwlock_wrlock", - ]; + let pre_link_args = TargetOptions::link_args( + LinkerFlavor::Ld, + &[ + "-e", + "elf_entry", + "-Bstatic", + "--gc-sections", + "-z", + "text", + "-z", + "norelro", + "--no-undefined", + "--error-unresolved-symbols", + "--no-undefined-version", + "-Bsymbolic", + "--export-dynamic", + // The following symbols are needed by libunwind, which is linked after + // libstd. Make sure they're included in the link. + "-u", + "__rust_abort", + "-u", + "__rust_c_alloc", + "-u", + "__rust_c_dealloc", + "-u", + "__rust_print_err", + "-u", + "__rust_rwlock_rdlock", + "-u", + "__rust_rwlock_unlock", + "-u", + "__rust_rwlock_wrlock", + ], + ); const EXPORT_SYMBOLS: &[&str] = &[ "sgx_entry", @@ -66,11 +69,7 @@ pub fn target() -> Target { features: "+rdrnd,+rdseed,+lvi-cfi,+lvi-load-hardening".into(), llvm_args: cvs!["--x86-experimental-lvi-inline-asm-hardening"], position_independent_executables: true, - pre_link_args: iter::once(( - LinkerFlavor::Lld(LldFlavor::Ld), - PRE_LINK_ARGS.iter().cloned().map(Cow::from).collect(), - )) - .collect(), + pre_link_args, override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(Cow::from).collect()), relax_elf_relocations: true, ..Default::default() diff --git a/compiler/rustc_target/src/spec/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/x86_64_linux_android.rs index 049cab0d554..6d19cf26574 100644 --- a/compiler/rustc_target/src/spec/x86_64_linux_android.rs +++ b/compiler/rustc_target/src/spec/x86_64_linux_android.rs @@ -6,7 +6,7 @@ pub fn target() -> Target { // https://developer.android.com/ndk/guides/abis.html#86-64 base.features = "+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt".into(); base.max_atomic_width = Some(64); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs index 2a697daeb28..0550b221fd9 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs @@ -2,7 +2,7 @@ use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::solaris_base::opts(); - base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".into()]); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.cpu = "x86-64".into(); base.vendor = "pc".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs index 0fa43481c9b..59a8cffca48 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs @@ -1,14 +1,11 @@ -use crate::spec::{LinkerFlavor, LldFlavor, Target}; +use crate::spec::{LinkerFlavor, Target}; pub fn target() -> Target { let mut base = super::windows_gnu_base::opts(); base.cpu = "x86-64".into(); - let gcc_pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); - gcc_pre_link_args.push("-m64".into()); // Use high-entropy 64 bit address space for ASLR - gcc_pre_link_args.push("-Wl,--high-entropy-va".into()); - base.pre_link_args - .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".into(), "i386pep".into()]); + base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pep", "--high-entropy-va"]); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-Wl,--high-entropy-va"]); base.max_atomic_width = Some(64); base.linker = Some("x86_64-w64-mingw32-gcc".into()); diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs index b5ff63e0532..d3909b3895e 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs @@ -3,8 +3,7 @@ use crate::spec::{LinkerFlavor, Target}; pub fn target() -> Target { let mut base = super::windows_gnullvm_base::opts(); base.cpu = "x86-64".into(); - let gcc_pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); - gcc_pre_link_args.push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.max_atomic_width = Some(64); base.linker = Some("x86_64-w64-mingw32-clang".into()); diff --git a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs b/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs index a02018266fb..cbe87589a70 100644 --- a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs +++ b/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs @@ -2,7 +2,7 @@ use crate::spec::{LinkerFlavor, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::solaris_base::opts(); - base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".into()]); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.cpu = "x86-64".into(); base.vendor = "sun".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs index 1f2b998a7ba..746f6478178 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::dragonfly_base::opts(); base.cpu = "x86-64".into(); base.max_atomic_width = Some(64); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs index c9aedd6ea82..b30784ed692 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::freebsd_base::opts(); base.cpu = "x86-64".into(); base.max_atomic_width = Some(64); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; base.supported_sanitizers = diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs index aebbd18c66a..d6d03362982 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::haiku_base::opts(); base.cpu = "x86-64".into(); base.max_atomic_width = Some(64); - base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".into()]); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; // This option is required to build executables on Haiku x86_64 diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs index 9529fa9640d..9f19c3a2b2a 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs @@ -2,7 +2,7 @@ use crate::spec::{LinkerFlavor, SanitizerSet, Target}; pub fn target() -> Target { let mut base = super::illumos_base::opts(); - base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".into(), "-std=c99".into()]); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-std=c99"]); base.cpu = "x86-64".into(); base.max_atomic_width = Some(64); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs index e525cfdde14..956be0353fa 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); base.cpu = "x86-64".into(); base.max_atomic_width = Some(64); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; base.static_position_independent_executables = true; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs index 863b41633e2..140882747c2 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs @@ -5,7 +5,7 @@ pub fn target() -> Target { base.cpu = "x86-64".into(); base.abi = "x32".into(); base.max_atomic_width = Some(64); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mx32".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-mx32"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; base.has_thread_local = false; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs index 8678f06e2cb..87e7784d1f9 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); base.cpu = "x86-64".into(); base.max_atomic_width = Some(64); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; base.static_position_independent_executables = true; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs index a7115dace1c..d3a67619aa8 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::netbsd_base::opts(); base.cpu = "x86-64".into(); base.max_atomic_width = Some(64); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; base.supported_sanitizers = SanitizerSet::ADDRESS diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs index 0db88d64ac0..593345a5f1d 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs @@ -10,7 +10,7 @@ pub fn target() -> Target { base.features = "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float".into(); base.code_model = Some(CodeModel::Kernel); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); Target { // FIXME: Some dispute, the linux-on-clang folks think this should use diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs index 11e9cc4abc0..f50c6bceec9 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::openbsd_base::opts(); base.cpu = "x86-64".into(); base.max_atomic_width = Some(64); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs index af8b9673c30..668ae905417 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::redox_base::opts(); base.cpu = "x86-64".into(); base.max_atomic_width = Some(64); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs index a94bbbf6ede..76d2013cf7f 100644 --- a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs @@ -1,14 +1,11 @@ -use crate::spec::{LinkerFlavor, LldFlavor, Target}; +use crate::spec::{LinkerFlavor, Target}; pub fn target() -> Target { let mut base = super::windows_uwp_gnu_base::opts(); base.cpu = "x86-64".into(); - let gcc_pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); - gcc_pre_link_args.push("-m64".into()); // Use high-entropy 64 bit address space for ASLR - gcc_pre_link_args.push("-Wl,--high-entropy-va".into()); - base.pre_link_args - .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".into(), "i386pep".into()]); + base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pep", "--high-entropy-va"]); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-Wl,--high-entropy-va"]); base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs index 16d29753e7d..1298974952f 100644 --- a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::vxworks_base::opts(); base.cpu = "x86-64".into(); base.max_atomic_width = Some(64); - base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into()); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; base.disable_redzone = true; diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index a63790b594d..90ff07cba02 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -220,7 +220,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { .map(|&(id, _)| (id, vec![])) .collect(); - infcx.process_registered_region_obligations(&body_id_map, None, full_env); + infcx.process_registered_region_obligations(&body_id_map, full_env); let region_data = infcx .inner diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index b37db4b9e18..2b26b916d32 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -407,11 +407,7 @@ fn resolve_negative_obligation<'cx, 'tcx>( // function bodies with closures). outlives_env.save_implied_bounds(CRATE_HIR_ID); - infcx.process_registered_region_obligations( - outlives_env.region_bound_pairs_map(), - Some(tcx.lifetimes.re_root_empty), - param_env, - ); + infcx.process_registered_region_obligations(outlives_env.region_bound_pairs_map(), param_env); let errors = infcx.resolve_regions(region_context, &outlives_env); diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 132c335a7e6..8d344591915 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -366,15 +366,9 @@ fn object_safety_violation_for_method( // Get an accurate span depending on the violation. violation.map(|v| { let node = tcx.hir().get_if_local(method.def_id); - let span = match (v, node) { - (MethodViolationCode::ReferencesSelfInput(arg), Some(node)) => node - .fn_decl() - .and_then(|decl| decl.inputs.get(arg + 1)) - .map_or(method.ident(tcx).span, |arg| arg.span), - (MethodViolationCode::UndispatchableReceiver, Some(node)) => node - .fn_decl() - .and_then(|decl| decl.inputs.get(0)) - .map_or(method.ident(tcx).span, |arg| arg.span), + let span = match (&v, node) { + (MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span, + (MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span, (MethodViolationCode::ReferencesSelfOutput, Some(node)) => { node.fn_decl().map_or(method.ident(tcx).span, |decl| decl.output.span()) } @@ -397,32 +391,41 @@ fn virtual_call_violation_for_method<'tcx>( // The method's first parameter must be named `self` if !method.fn_has_self_parameter { - // We'll attempt to provide a structured suggestion for `Self: Sized`. - let sugg = - tcx.hir().get_if_local(method.def_id).as_ref().and_then(|node| node.generics()).map( - |generics| match generics.predicates { - [] => (" where Self: Sized", generics.where_clause_span), - [.., pred] => (", Self: Sized", pred.span().shrink_to_hi()), - }, - ); - // Get the span pointing at where the `self` receiver should be. - let sm = tcx.sess.source_map(); - let self_span = method.ident(tcx).span.to(tcx - .hir() - .span_if_local(method.def_id) - .unwrap_or_else(|| sm.next_point(method.ident(tcx).span)) - .shrink_to_hi()); - let self_span = sm.span_through_char(self_span, '(').shrink_to_hi(); - return Some(MethodViolationCode::StaticMethod( - sugg, - self_span, - !sig.inputs().skip_binder().is_empty(), - )); + let sugg = if let Some(hir::Node::TraitItem(hir::TraitItem { + generics, + kind: hir::TraitItemKind::Fn(sig, _), + .. + })) = tcx.hir().get_if_local(method.def_id).as_ref() + { + let sm = tcx.sess.source_map(); + Some(( + ( + format!("&self{}", if sig.decl.inputs.is_empty() { "" } else { ", " }), + sm.span_through_char(sig.span, '(').shrink_to_hi(), + ), + ( + format!("{} Self: Sized", generics.add_where_or_trailing_comma()), + generics.tail_span_for_predicate_suggestion(), + ), + )) + } else { + None + }; + return Some(MethodViolationCode::StaticMethod(sugg)); } - for (i, &input_ty) in sig.skip_binder().inputs()[1..].iter().enumerate() { + for (i, &input_ty) in sig.skip_binder().inputs().iter().enumerate().skip(1) { if contains_illegal_self_type_reference(tcx, trait_def_id, sig.rebind(input_ty)) { - return Some(MethodViolationCode::ReferencesSelfInput(i)); + let span = if let Some(hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(sig, _), + .. + })) = tcx.hir().get_if_local(method.def_id).as_ref() + { + Some(sig.decl.inputs[i].span) + } else { + None + }; + return Some(MethodViolationCode::ReferencesSelfInput(span)); } } if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output()) { @@ -456,7 +459,16 @@ fn virtual_call_violation_for_method<'tcx>( // `Receiver: Unsize<Receiver[Self => dyn Trait]>`. if receiver_ty != tcx.types.self_param { if !receiver_is_dispatchable(tcx, method, receiver_ty) { - return Some(MethodViolationCode::UndispatchableReceiver); + let span = if let Some(hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(sig, _), + .. + })) = tcx.hir().get_if_local(method.def_id).as_ref() + { + Some(sig.decl.inputs[0].span) + } else { + None + }; + return Some(MethodViolationCode::UndispatchableReceiver(span)); } else { // Do sanity check to make sure the receiver actually has the layout of a pointer. diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 82c54291a5d..aba4f144d4b 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -28,7 +28,6 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::resolve::OpportunisticRegionResolver; -use rustc_infer::traits::ObligationCauseCode; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::fold::{MaxUniverse, TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::subst::Subst; @@ -252,22 +251,10 @@ fn project_and_unify_type<'cx, 'tcx>( Err(InProgress) => return ProjectAndUnifyResult::Recursive, }; debug!(?normalized, ?obligations, "project_and_unify_type result"); - let actual = obligation.predicate.term; - // HACK: lazy TAIT would regress src/test/ui/impl-trait/nested-return-type2.rs, so we add - // a back-compat hack hat converts the RPITs into inference vars, just like they were before - // lazy TAIT. - // This does not affect TAITs in general, as tested in the nested-return-type-tait* tests. - let InferOk { value: actual, obligations: new } = - selcx.infcx().replace_opaque_types_with_inference_vars( - actual, - obligation.cause.body_id, - obligation.cause.span, - ObligationCauseCode::MiscObligation, - obligation.param_env, - ); - obligations.extend(new); - - match infcx.at(&obligation.cause, obligation.param_env).eq(normalized, actual) { + match infcx + .at(&obligation.cause, obligation.param_env) + .eq(normalized, obligation.predicate.term) + { Ok(InferOk { obligations: inferred_obligations, value: () }) => { obligations.extend(inferred_obligations); ProjectAndUnifyResult::Holds(obligations) diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 95f1e224a4c..a1861529b59 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -452,7 +452,7 @@ fn report_conflicting_impls( match used_to_be_allowed { None => { let reported = if overlap.with_impl.is_local() - || !tcx.orphan_check_crate(()).contains(&impl_def_id) + || tcx.orphan_check_impl(impl_def_id).is_ok() { let err = struct_span_err!(tcx.sess, impl_span, E0119, ""); Some(decorate( diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 45c011b78e3..8ffffbed93c 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -32,11 +32,6 @@ use rustc_ty_utils::representability::{self, Representability}; use std::iter; use std::ops::ControlFlow; -pub fn check_wf_new(tcx: TyCtxt<'_>) { - let visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx); - tcx.hir().par_visit_all_item_likes(&visit); -} - pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { match tcx.sess.target.is_abi_supported(abi) { Some(true) => (), @@ -754,7 +749,7 @@ fn check_opaque_meets_bounds<'tcx>( }); } -pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { +fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { debug!( "check_item_type(it.def_id={:?}, it.name={})", id.def_id, @@ -1543,12 +1538,6 @@ pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { } } -pub(super) use wfcheck::check_item_well_formed; - -pub(super) use wfcheck::check_trait_item as check_trait_item_well_formed; - -pub(super) use wfcheck::check_impl_item as check_impl_item_well_formed; - fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed { struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing") .span_label(span, "recursive `async fn`") diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index f09c7f51f47..6ee989070b4 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -225,7 +225,7 @@ pub fn resolve_interior<'a, 'tcx>( // Note that each region slot in the types gets a new fresh late bound region, // which means that none of the regions inside relate to any other, even if // typeck had previously found constraints that would cause them to be related. - let folded = fcx.tcx.fold_regions(erased, &mut false, |_, current_depth| { + let folded = fcx.tcx.fold_regions(erased, |_, current_depth| { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon(counter), diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index e26f211c1c1..0ede9ef7756 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -93,11 +93,7 @@ mod upvar; mod wfcheck; pub mod writeback; -use check::{ - check_abi, check_fn, check_impl_item_well_formed, check_item_well_formed, check_mod_item_types, - check_trait_item_well_formed, -}; -pub use check::{check_item_type, check_wf_new}; +use check::{check_abi, check_fn, check_mod_item_types}; pub use diverges::Diverges; pub use expectation::Expectation; pub use fn_ctxt::*; @@ -245,6 +241,7 @@ impl<'tcx> EnclosingBreakables<'tcx> { pub fn provide(providers: &mut Providers) { method::provide(providers); + wfcheck::provide(providers); *providers = Providers { typeck_item_bodies, typeck_const_arg, @@ -253,9 +250,6 @@ pub fn provide(providers: &mut Providers) { has_typeck_results, adt_destructor, used_trait_imports, - check_item_well_formed, - check_trait_item_well_formed, - check_impl_item_well_formed, check_mod_item_types, region_scope_tree, ..*providers diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs index 161ec31793d..0ce63922098 100644 --- a/compiler/rustc_typeck/src/check/regionck.rs +++ b/compiler/rustc_typeck/src/check/regionck.rs @@ -366,7 +366,6 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { fn resolve_regions_and_report_errors(&self) { self.infcx.process_registered_region_obligations( self.outlives_environment.region_bound_pairs_map(), - Some(self.tcx.lifetimes.re_root_empty), self.param_env, ); diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 79312153895..67eb88b73fd 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -7,21 +7,18 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit as hir_visit; -use rustc_hir::intravisit::Visitor; -use rustc_hir::itemlikevisit::ParItemLikeVisitor; use rustc_hir::lang_items::LangItem; use rustc_hir::ItemKind; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::outlives::obligations::TypeOutlives; use rustc_infer::infer::region_constraints::GenericKind; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; -use rustc_middle::hir::nested_filter; +use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst}; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ - self, AdtKind, EarlyBinder, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, - TypeSuperFoldable, TypeVisitor, + self, AdtKind, DefIdTree, EarlyBinder, GenericParamDefKind, ToPredicate, Ty, TyCtxt, + TypeFoldable, TypeSuperFoldable, TypeVisitor, }; use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Ident, Symbol}; @@ -70,6 +67,23 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> { } } +fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { + let node = tcx.hir().expect_owner(def_id); + match node { + hir::OwnerNode::Crate(_) => {} + hir::OwnerNode::Item(item) => check_item(tcx, item), + hir::OwnerNode::TraitItem(item) => check_trait_item(tcx, item), + hir::OwnerNode::ImplItem(item) => check_impl_item(tcx, item), + hir::OwnerNode::ForeignItem(item) => check_foreign_item(tcx, item), + } + + if let Some(generics) = node.generics() { + for param in generics.params { + check_param_wf(tcx, param) + } + } +} + /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are /// well-formed, meaning that they do not require any constraints not declared in the struct /// definition itself. For example, this definition would be illegal: @@ -84,8 +98,8 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> { /// not included it frequently leads to confusing errors in fn bodies. So it's better to check /// the types first. #[instrument(skip(tcx), level = "debug")] -pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { - let item = tcx.hir().expect_item(def_id); +fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { + let def_id = item.def_id; debug!( ?item.def_id, @@ -156,20 +170,6 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { hir::ItemKind::Const(ty, ..) => { check_item_type(tcx, item.def_id, ty.span, false); } - hir::ItemKind::ForeignMod { items, .. } => { - for it in items.iter() { - let it = tcx.hir().foreign_item(it.id); - match it.kind { - hir::ForeignItemKind::Fn(decl, ..) => { - check_item_fn(tcx, it.def_id, it.ident, it.span, decl) - } - hir::ForeignItemKind::Static(ty, ..) => { - check_item_type(tcx, it.def_id, ty.span, true) - } - hir::ForeignItemKind::Type => (), - } - } - } hir::ItemKind::Struct(ref struct_def, ref ast_generics) => { check_type_defn(tcx, item, false, |fcx| vec![fcx.non_enum_variant(struct_def)]); @@ -191,13 +191,31 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { hir::ItemKind::TraitAlias(..) => { check_trait(tcx, item); } + // `ForeignItem`s are handled separately. + hir::ItemKind::ForeignMod { .. } => {} _ => {} } } -pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let trait_item = tcx.hir().expect_trait_item(def_id); +fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) { + let def_id = item.def_id; + + debug!( + ?item.def_id, + item.name = ? tcx.def_path_str(def_id.to_def_id()) + ); + + match item.kind { + hir::ForeignItemKind::Fn(decl, ..) => { + check_item_fn(tcx, item.def_id, item.ident, item.span, decl) + } + hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, item.def_id, ty.span, true), + hir::ForeignItemKind::Type => (), + } +} + +fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) { + let def_id = trait_item.def_id; let (method_sig, span) = match trait_item.kind { hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span), @@ -207,7 +225,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { check_object_unsafe_self_trait_by_name(tcx, trait_item); check_associated_item(tcx, trait_item.def_id, span, method_sig); - let encl_trait_def_id = tcx.hir().get_parent_item(hir_id); + let encl_trait_def_id = tcx.local_parent(def_id); let encl_trait = tcx.hir().expect_item(encl_trait_def_id); let encl_trait_def_id = encl_trait.def_id.to_def_id(); let fn_lang_item_name = if Some(encl_trait_def_id) == tcx.lang_items().fn_trait() { @@ -596,13 +614,7 @@ fn ty_known_to_outlive<'tcx>( ) -> bool { resolve_regions_with_wf_tys(tcx, id, param_env, &wf_tys, |infcx, region_bound_pairs| { let origin = infer::RelateParamBound(DUMMY_SP, ty, None); - let outlives = &mut TypeOutlives::new( - infcx, - tcx, - region_bound_pairs, - Some(infcx.tcx.lifetimes.re_root_empty), - param_env, - ); + let outlives = &mut TypeOutlives::new(infcx, tcx, region_bound_pairs, None, param_env); outlives.type_must_outlive(origin, ty, region); }) } @@ -770,8 +782,8 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem } } -pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { - let impl_item = tcx.hir().expect_impl_item(def_id); +fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) { + let def_id = impl_item.def_id; let (method_sig, span) = match impl_item.kind { hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span), @@ -780,7 +792,7 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { _ => (None, impl_item.span), }; - check_associated_item(tcx, impl_item.def_id, span, method_sig); + check_associated_item(tcx, def_id, span, method_sig); } fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { @@ -990,6 +1002,15 @@ fn check_type_defn<'tcx, F>( let packed = tcx.adt_def(item.def_id).repr().packed(); for variant in &variants { + // All field types must be well-formed. + for field in &variant.fields { + fcx.register_wf_obligation( + field.ty.into(), + field.span, + ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(field.def_id))), + ) + } + // For DST, or when drop needs to copy things around, all // intermediate types must be sized. let needs_drop_copy = || { @@ -1006,6 +1027,7 @@ fn check_type_defn<'tcx, F>( } } }; + // All fields (except for possibly the last) should be sized. let all_sized = all_sized || variant.fields.is_empty() || needs_drop_copy(); let unsized_len = if all_sized { 0 } else { 1 }; for (idx, field) in @@ -1030,15 +1052,6 @@ fn check_type_defn<'tcx, F>( ); } - // All field types must be well-formed. - for field in &variant.fields { - fcx.register_wf_obligation( - field.ty.into(), - field.span, - ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(field.def_id))), - ) - } - // Explicit `enum` discriminant values must const-evaluate successfully. if let Some(discr_def_id) = variant.explicit_discr { let discr_substs = InternalSubsts::identity_for_item(tcx, discr_def_id.to_def_id()); @@ -1827,67 +1840,12 @@ fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, mut span: Span, id: hir::HirI fcx.select_all_obligations_or_error(); } -#[derive(Clone, Copy)] -pub struct CheckTypeWellFormedVisitor<'tcx> { - tcx: TyCtxt<'tcx>, -} - -impl<'tcx> CheckTypeWellFormedVisitor<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>) -> CheckTypeWellFormedVisitor<'tcx> { - CheckTypeWellFormedVisitor { tcx } - } -} - -impl<'tcx> ParItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> { - fn visit_item(&self, i: &'tcx hir::Item<'tcx>) { - Visitor::visit_item(&mut self.clone(), i); - } - - fn visit_trait_item(&self, trait_item: &'tcx hir::TraitItem<'tcx>) { - Visitor::visit_trait_item(&mut self.clone(), trait_item); - } - - fn visit_impl_item(&self, impl_item: &'tcx hir::ImplItem<'tcx>) { - Visitor::visit_impl_item(&mut self.clone(), impl_item); - } - - fn visit_foreign_item(&self, foreign_item: &'tcx hir::ForeignItem<'tcx>) { - Visitor::visit_foreign_item(&mut self.clone(), foreign_item) - } -} - -impl<'tcx> Visitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> { - type NestedFilter = nested_filter::OnlyBodies; - - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() - } - - #[instrument(skip(self, i), level = "debug")] - fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) { - trace!(?i); - self.tcx.ensure().check_item_well_formed(i.def_id); - hir_visit::walk_item(self, i); - } - - #[instrument(skip(self, trait_item), level = "debug")] - fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { - trace!(?trait_item); - self.tcx.ensure().check_trait_item_well_formed(trait_item.def_id); - hir_visit::walk_trait_item(self, trait_item); - } - - #[instrument(skip(self, impl_item), level = "debug")] - fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { - trace!(?impl_item); - self.tcx.ensure().check_impl_item_well_formed(impl_item.def_id); - hir_visit::walk_impl_item(self, impl_item); - } - - fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) { - check_param_wf(self.tcx, p); - hir_visit::walk_generic_param(self, p); - } +fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalDefId) { + let items = tcx.hir_module_items(module); + items.par_items(|item| tcx.ensure().check_well_formed(item.def_id)); + items.par_impl_items(|item| tcx.ensure().check_well_formed(item.def_id)); + items.par_trait_items(|item| tcx.ensure().check_well_formed(item.def_id)); + items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.def_id)); } /////////////////////////////////////////////////////////////////////////// @@ -1972,3 +1930,7 @@ fn error_392( err.span_label(span, "unused parameter"); err } + +pub fn provide(providers: &mut Providers) { + *providers = Providers { check_mod_type_wf, check_well_formed, ..*providers }; +} diff --git a/compiler/rustc_typeck/src/coherence/mod.rs b/compiler/rustc_typeck/src/coherence/mod.rs index 3903448a007..447ec87f302 100644 --- a/compiler/rustc_typeck/src/coherence/mod.rs +++ b/compiler/rustc_typeck/src/coherence/mod.rs @@ -146,7 +146,7 @@ pub fn provide(providers: &mut Providers) { use self::builtin::coerce_unsized_info; use self::inherent_impls::{crate_incoherent_impls, crate_inherent_impls, inherent_impls}; use self::inherent_impls_overlap::crate_inherent_impls_overlap_check; - use self::orphan::orphan_check_crate; + use self::orphan::orphan_check_impl; *providers = Providers { coherent_trait, @@ -155,7 +155,7 @@ pub fn provide(providers: &mut Providers) { inherent_impls, crate_inherent_impls_overlap_check, coerce_unsized_info, - orphan_check_crate, + orphan_check_impl, ..*providers }; } @@ -171,21 +171,12 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) { check_impl(tcx, impl_def_id, trait_ref); check_object_overlap(tcx, impl_def_id, trait_ref); - } - builtin::check_trait(tcx, def_id); -} -pub fn check_coherence(tcx: TyCtxt<'_>) { - tcx.sess.time("unsafety_checking", || unsafety::check(tcx)); - tcx.ensure().orphan_check_crate(()); - - for &trait_def_id in tcx.all_local_trait_impls(()).keys() { - tcx.ensure().coherent_trait(trait_def_id); + tcx.sess.time("unsafety_checking", || unsafety::check_item(tcx, impl_def_id)); + tcx.sess.time("orphan_checking", || tcx.ensure().orphan_check_impl(impl_def_id)); } - // these queries are executed for side-effects (error reporting): - tcx.ensure().crate_inherent_impls(()); - tcx.ensure().crate_inherent_impls_overlap_check(()); + builtin::check_trait(tcx, def_id); } /// Checks whether an impl overlaps with the automatic `impl Trait for dyn Trait`. diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs index 9ddfc8d5cc8..f3a043a08a3 100644 --- a/compiler/rustc_typeck/src/coherence/orphan.rs +++ b/compiler/rustc_typeck/src/coherence/orphan.rs @@ -18,26 +18,29 @@ use rustc_span::Span; use rustc_trait_selection::traits; use std::ops::ControlFlow; -pub(super) fn orphan_check_crate(tcx: TyCtxt<'_>, (): ()) -> &[LocalDefId] { - let mut errors = Vec::new(); - for (&trait_def_id, impls_of_trait) in tcx.all_local_trait_impls(()) { - for &impl_of_trait in impls_of_trait { - match orphan_check_impl(tcx, impl_of_trait) { - Ok(()) => {} - Err(_) => errors.push(impl_of_trait), - } - } +#[instrument(skip(tcx), level = "debug")] +pub(crate) fn orphan_check_impl( + tcx: TyCtxt<'_>, + impl_def_id: LocalDefId, +) -> Result<(), ErrorGuaranteed> { + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); + if let Some(err) = trait_ref.error_reported() { + return Err(err); + } - if tcx.trait_is_auto(trait_def_id) { - lint_auto_trait_impls(tcx, trait_def_id, impls_of_trait); - } + let ret = do_orphan_check_impl(tcx, trait_ref, impl_def_id); + if tcx.trait_is_auto(trait_ref.def_id) { + lint_auto_trait_impl(tcx, trait_ref, impl_def_id); } - tcx.arena.alloc_slice(&errors) + + ret } -#[instrument(skip(tcx), level = "debug")] -fn orphan_check_impl(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { - let trait_ref = tcx.impl_trait_ref(def_id).unwrap(); +fn do_orphan_check_impl<'tcx>( + tcx: TyCtxt<'tcx>, + trait_ref: ty::TraitRef<'tcx>, + def_id: LocalDefId, +) -> Result<(), ErrorGuaranteed> { let trait_def_id = trait_ref.def_id; let item = tcx.hir().item(hir::ItemId { def_id }); @@ -329,89 +332,82 @@ fn emit_orphan_check_error<'tcx>( /// Lint impls of auto traits if they are likely to have /// unsound or surprising effects on auto impls. -fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDefId]) { - let mut non_covering_impls = Vec::new(); - for &impl_def_id in impls { - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); - if trait_ref.references_error() { - return; - } +fn lint_auto_trait_impl<'tcx>( + tcx: TyCtxt<'tcx>, + trait_ref: ty::TraitRef<'tcx>, + impl_def_id: LocalDefId, +) { + if tcx.impl_polarity(impl_def_id) != ImplPolarity::Positive { + return; + } - if tcx.impl_polarity(impl_def_id) != ImplPolarity::Positive { + assert_eq!(trait_ref.substs.len(), 1); + let self_ty = trait_ref.self_ty(); + let (self_type_did, substs) = match self_ty.kind() { + ty::Adt(def, substs) => (def.did(), substs), + _ => { + // FIXME: should also lint for stuff like `&i32` but + // considering that auto traits are unstable, that + // isn't too important for now as this only affects + // crates using `nightly`, and std. return; } + }; - assert_eq!(trait_ref.substs.len(), 1); - let self_ty = trait_ref.self_ty(); - let (self_type_did, substs) = match self_ty.kind() { - ty::Adt(def, substs) => (def.did(), substs), - _ => { - // FIXME: should also lint for stuff like `&i32` but - // considering that auto traits are unstable, that - // isn't too important for now as this only affects - // crates using `nightly`, and std. - continue; - } - }; + // Impls which completely cover a given root type are fine as they + // disable auto impls entirely. So only lint if the substs + // are not a permutation of the identity substs. + let Err(arg) = tcx.uses_unique_generic_params(substs, IgnoreRegions::Yes) else { + // ok + return; + }; - // Impls which completely cover a given root type are fine as they - // disable auto impls entirely. So only lint if the substs - // are not a permutation of the identity substs. - match tcx.uses_unique_generic_params(substs, IgnoreRegions::Yes) { - Ok(()) => {} // ok - Err(arg) => { - // Ideally: - // - // - compute the requirements for the auto impl candidate - // - check whether these are implied by the non covering impls - // - if not, emit the lint - // - // What we do here is a bit simpler: - // - // - badly check if an auto impl candidate definitely does not apply - // for the given simplified type - // - if so, do not lint - if fast_reject_auto_impl(tcx, trait_def_id, self_ty) { - // ok - } else { - non_covering_impls.push((impl_def_id, self_type_did, arg)); - } - } - } + // Ideally: + // + // - compute the requirements for the auto impl candidate + // - check whether these are implied by the non covering impls + // - if not, emit the lint + // + // What we do here is a bit simpler: + // + // - badly check if an auto impl candidate definitely does not apply + // for the given simplified type + // - if so, do not lint + if fast_reject_auto_impl(tcx, trait_ref.def_id, self_ty) { + // ok + return; } - for &(impl_def_id, self_type_did, arg) in &non_covering_impls { - tcx.struct_span_lint_hir( - lint::builtin::SUSPICIOUS_AUTO_TRAIT_IMPLS, - tcx.hir().local_def_id_to_hir_id(impl_def_id), - tcx.def_span(impl_def_id), - |err| { - let item_span = tcx.def_span(self_type_did); - let self_descr = tcx.def_kind(self_type_did).descr(self_type_did); - let mut err = err.build(&format!( - "cross-crate traits with a default impl, like `{}`, \ + tcx.struct_span_lint_hir( + lint::builtin::SUSPICIOUS_AUTO_TRAIT_IMPLS, + tcx.hir().local_def_id_to_hir_id(impl_def_id), + tcx.def_span(impl_def_id), + |err| { + let item_span = tcx.def_span(self_type_did); + let self_descr = tcx.def_kind(self_type_did).descr(self_type_did); + let mut err = err.build(&format!( + "cross-crate traits with a default impl, like `{}`, \ should not be specialized", - tcx.def_path_str(trait_def_id), - )); - match arg { - ty::util::NotUniqueParam::DuplicateParam(arg) => { - err.note(&format!("`{}` is mentioned multiple times", arg)); - } - ty::util::NotUniqueParam::NotParam(arg) => { - err.note(&format!("`{}` is not a generic parameter", arg)); - } + tcx.def_path_str(trait_ref.def_id), + )); + match arg { + ty::util::NotUniqueParam::DuplicateParam(arg) => { + err.note(&format!("`{}` is mentioned multiple times", arg)); } - err.span_note( - item_span, - &format!( - "try using the same sequence of generic parameters as the {} definition", - self_descr, - ), - ); - err.emit(); - }, - ); - } + ty::util::NotUniqueParam::NotParam(arg) => { + err.note(&format!("`{}` is not a generic parameter", arg)); + } + } + err.span_note( + item_span, + &format!( + "try using the same sequence of generic parameters as the {} definition", + self_descr, + ), + ); + err.emit(); + }, + ); } fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty: Ty<'tcx>) -> bool { diff --git a/compiler/rustc_typeck/src/coherence/unsafety.rs b/compiler/rustc_typeck/src/coherence/unsafety.rs index 3cfc96ccbfd..e45fb5fe41c 100644 --- a/compiler/rustc_typeck/src/coherence/unsafety.rs +++ b/compiler/rustc_typeck/src/coherence/unsafety.rs @@ -6,37 +6,18 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::Unsafety; use rustc_middle::ty::TyCtxt; +use rustc_span::def_id::LocalDefId; -pub fn check(tcx: TyCtxt<'_>) { - for id in tcx.hir().items() { - if matches!(tcx.def_kind(id.def_id), DefKind::Impl) { - let item = tcx.hir().item(id); - if let hir::ItemKind::Impl(ref impl_) = item.kind { - check_unsafety_coherence( - tcx, - item, - Some(&impl_.generics), - impl_.unsafety, - impl_.polarity, - ); - } - } - } -} +pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { + debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Impl)); + let item = tcx.hir().expect_item(def_id); + let hir::ItemKind::Impl(ref impl_) = item.kind else { bug!() }; -fn check_unsafety_coherence<'tcx>( - tcx: TyCtxt<'tcx>, - item: &hir::Item<'_>, - impl_generics: Option<&hir::Generics<'_>>, - unsafety: hir::Unsafety, - polarity: hir::ImplPolarity, -) { if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) { let trait_def = tcx.trait_def(trait_ref.def_id); - let unsafe_attr = impl_generics.and_then(|generics| { - generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle") - }); - match (trait_def.unsafety, unsafe_attr, unsafety, polarity) { + let unsafe_attr = + impl_.generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); + match (trait_def.unsafety, unsafe_attr, impl_.unsafety, impl_.polarity) { (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => { struct_span_err!( tcx.sess, diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 1f2e6ad86bd..2a52167c597 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -393,7 +393,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { } fn ct_infer(&self, ty: Ty<'tcx>, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> { - let ty = self.tcx.fold_regions(ty, &mut false, |r, _| match *r { + let ty = self.tcx.fold_regions(ty, |r, _| match *r { ty::ReErased => self.tcx.lifetimes.re_static, _ => r, }); @@ -1917,7 +1917,7 @@ fn infer_return_ty_for_fn_sig<'tcx>( Some(ty) => { let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id]; // Typeck doesn't expect erased regions to be returned from `type_of`. - let fn_sig = tcx.fold_regions(fn_sig, &mut false, |r, _| match *r { + let fn_sig = tcx.fold_regions(fn_sig, |r, _| match *r { ty::ReErased => tcx.lifetimes.re_static, _ => r, }); diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 7011dd6e15c..6ee2b544916 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -772,7 +772,7 @@ fn infer_placeholder_type<'a>( } // Typeck doesn't expect erased regions to be returned from `type_of`. - tcx.fold_regions(ty, &mut false, |r, _| match *r { + tcx.fold_regions(ty, |r, _| match *r { ty::ReErased => tcx.lifetimes.re_static, _ => r, }) diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs index c089d25d222..981c35e184b 100644 --- a/compiler/rustc_typeck/src/impl_wf_check.rs +++ b/compiler/rustc_typeck/src/impl_wf_check.rs @@ -13,7 +13,6 @@ use min_specialization::check_min_specialization; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::struct_span_err; -use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::query::Providers; @@ -54,25 +53,15 @@ mod min_specialization; /// impl<'a> Trait<Foo> for Bar { type X = &'a i32; } /// // ^ 'a is unused and appears in assoc type, error /// ``` -pub fn impl_wf_check(tcx: TyCtxt<'_>) { - // We will tag this as part of the WF check -- logically, it is, - // but it's one that we must perform earlier than the rest of - // WfCheck. - tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)) -} - fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { let min_specialization = tcx.features().min_specialization; let module = tcx.hir_module_items(module_def_id); for id in module.items() { if matches!(tcx.def_kind(id.def_id), DefKind::Impl) { - let item = tcx.hir().item(id); - if let hir::ItemKind::Impl(ref impl_) = item.kind { - enforce_impl_params_are_constrained(tcx, item.def_id, impl_.items); - enforce_impl_items_are_distinct(tcx, impl_.items); - if min_specialization { - check_min_specialization(tcx, item.def_id.to_def_id(), item.span); - } + enforce_impl_params_are_constrained(tcx, id.def_id); + enforce_impl_items_are_distinct(tcx, id.def_id); + if min_specialization { + check_min_specialization(tcx, id.def_id); } } } @@ -82,11 +71,7 @@ pub fn provide(providers: &mut Providers) { *providers = Providers { check_mod_impl_wf, ..*providers }; } -fn enforce_impl_params_are_constrained( - tcx: TyCtxt<'_>, - impl_def_id: LocalDefId, - impl_item_refs: &[hir::ImplItemRef], -) { +fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) { // Every lifetime used in an associated type must be constrained. let impl_self_ty = tcx.type_of(impl_def_id); if impl_self_ty.references_error() { @@ -114,9 +99,9 @@ fn enforce_impl_params_are_constrained( ); // Disallow unconstrained lifetimes, but only if they appear in assoc types. - let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs + let lifetimes_in_associated_types: FxHashSet<_> = tcx + .associated_item_def_ids(impl_def_id) .iter() - .map(|item_ref| item_ref.id.def_id) .flat_map(|def_id| { let item = tcx.associated_item(def_id); match item.kind { @@ -216,33 +201,32 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: &str) } /// Enforce that we do not have two items in an impl with the same name. -fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplItemRef]) { +fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) { let mut seen_type_items = FxHashMap::default(); let mut seen_value_items = FxHashMap::default(); - for impl_item_ref in impl_item_refs { - let impl_item = tcx.hir().impl_item(impl_item_ref.id); + for &impl_item_ref in tcx.associated_item_def_ids(impl_def_id) { + let impl_item = tcx.associated_item(impl_item_ref); let seen_items = match impl_item.kind { - hir::ImplItemKind::TyAlias(_) => &mut seen_type_items, + ty::AssocKind::Type => &mut seen_type_items, _ => &mut seen_value_items, }; - match seen_items.entry(impl_item.ident.normalize_to_macros_2_0()) { + let span = tcx.def_span(impl_item_ref); + let ident = impl_item.ident(tcx); + match seen_items.entry(ident.normalize_to_macros_2_0()) { Occupied(entry) => { let mut err = struct_span_err!( tcx.sess, - impl_item.span, + span, E0201, "duplicate definitions with name `{}`:", - impl_item.ident - ); - err.span_label( - *entry.get(), - format!("previous definition of `{}` here", impl_item.ident), + ident ); - err.span_label(impl_item.span, "duplicate definition"); + err.span_label(*entry.get(), format!("previous definition of `{}` here", ident)); + err.span_label(span, "duplicate definition"); err.emit(); } Vacant(entry) => { - entry.insert(impl_item.span); + entry.insert(span); } } } diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index 0ecc28e6054..f07396ce74f 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -79,19 +79,19 @@ use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_span::Span; use rustc_trait_selection::traits::{self, translate_substs, wf}; -pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: DefId, span: Span) { +pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) { if let Some(node) = parent_specialization_node(tcx, impl_def_id) { tcx.infer_ctxt().enter(|infcx| { - check_always_applicable(&infcx, impl_def_id, node, span); + check_always_applicable(&infcx, impl_def_id, node); }); } } -fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: DefId) -> Option<Node> { +fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Option<Node> { let trait_ref = tcx.impl_trait_ref(impl1_def_id)?; let trait_def = tcx.trait_def(trait_ref.def_id); - let impl2_node = trait_def.ancestors(tcx, impl1_def_id).ok()?.nth(1)?; + let impl2_node = trait_def.ancestors(tcx, impl1_def_id.to_def_id()).ok()?.nth(1)?; let always_applicable_trait = matches!(trait_def.specialization_kind, TraitSpecializationKind::AlwaysApplicable); @@ -103,15 +103,8 @@ fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: DefId) -> Option<No } /// Check that `impl1` is a sound specialization -fn check_always_applicable( - infcx: &InferCtxt<'_, '_>, - impl1_def_id: DefId, - impl2_node: Node, - span: Span, -) { - if let Some((impl1_substs, impl2_substs)) = - get_impl_substs(infcx, impl1_def_id, impl2_node, span) - { +fn check_always_applicable(infcx: &InferCtxt<'_, '_>, impl1_def_id: LocalDefId, impl2_node: Node) { + if let Some((impl1_substs, impl2_substs)) = get_impl_substs(infcx, impl1_def_id, impl2_node) { let impl2_def_id = impl2_node.def_id(); debug!( "check_always_applicable(\nimpl1_def_id={:?},\nimpl2_def_id={:?},\nimpl2_substs={:?}\n)", @@ -126,17 +119,10 @@ fn check_always_applicable( unconstrained_parent_impl_substs(tcx, impl2_def_id, impl2_substs) }; + let span = tcx.def_span(impl1_def_id); check_static_lifetimes(tcx, &parent_substs, span); check_duplicate_params(tcx, impl1_substs, &parent_substs, span); - - check_predicates( - infcx, - impl1_def_id.expect_local(), - impl1_substs, - impl2_node, - impl2_substs, - span, - ); + check_predicates(infcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span); } } @@ -152,20 +138,21 @@ fn check_always_applicable( /// Would return `S1 = [C]` and `S2 = [Vec<C>, C]`. fn get_impl_substs<'tcx>( infcx: &InferCtxt<'_, 'tcx>, - impl1_def_id: DefId, + impl1_def_id: LocalDefId, impl2_node: Node, - span: Span, ) -> Option<(SubstsRef<'tcx>, SubstsRef<'tcx>)> { let tcx = infcx.tcx; let param_env = tcx.param_env(impl1_def_id); - let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id); - let impl2_substs = translate_substs(infcx, param_env, impl1_def_id, impl1_substs, impl2_node); + let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id()); + let impl2_substs = + translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node); // Conservatively use an empty `ParamEnv`. let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty()); - infcx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env); + infcx.resolve_regions_and_report_errors(impl1_def_id.to_def_id(), &outlives_env); let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else { + let span = tcx.def_span(impl1_def_id); tcx.sess.emit_err(SubstsOnOverriddenImpl { span }); return None; }; diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index d613edf0ab0..b6d4f5fcda6 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -509,11 +509,21 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { } tcx.sess.track_errors(|| { - tcx.sess.time("impl_wf_inference", || impl_wf_check::impl_wf_check(tcx)); + tcx.sess.time("impl_wf_inference", || { + tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)) + }); })?; tcx.sess.track_errors(|| { - tcx.sess.time("coherence_checking", || coherence::check_coherence(tcx)); + tcx.sess.time("coherence_checking", || { + for &trait_def_id in tcx.all_local_trait_impls(()).keys() { + tcx.ensure().coherent_trait(trait_def_id); + } + + // these queries are executed for side-effects (error reporting): + tcx.ensure().crate_inherent_impls(()); + tcx.ensure().crate_inherent_impls_overlap_check(()); + }); })?; if tcx.features().rustc_attrs { @@ -523,7 +533,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { } tcx.sess.track_errors(|| { - tcx.sess.time("wf_checking", || check::check_wf_new(tcx)); + tcx.sess.time("wf_checking", || { + tcx.hir().par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module)) + }); })?; // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync. diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index 807c035fdbd..203e5dff0c7 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -33,6 +33,14 @@ pub struct ThinBox<T: ?Sized> { _marker: PhantomData<T>, } +/// `ThinBox<T>` is `Send` if `T` is `Send` because the data is owned. +#[unstable(feature = "thin_box", issue = "92791")] +unsafe impl<T: ?Sized + Send> Send for ThinBox<T> {} + +/// `ThinBox<T>` is `Sync` if `T` is `Sync` because the data is owned. +#[unstable(feature = "thin_box", issue = "92791")] +unsafe impl<T: ?Sized + Sync> Sync for ThinBox<T> {} + #[unstable(feature = "thin_box", issue = "92791")] impl<T> ThinBox<T> { /// Moves a type to the heap with its `Metadata` stored in the heap allocation instead of on diff --git a/library/alloc/tests/fmt.rs b/library/alloc/tests/fmt.rs index 67e12c612db..5ee6db43fda 100644 --- a/library/alloc/tests/fmt.rs +++ b/library/alloc/tests/fmt.rs @@ -207,7 +207,7 @@ fn test_format_macro_interface() { { let val = usize::MAX; let exp = format!("{val:#x}"); - t!(format!("{:p}", val as *const isize), exp); + t!(format!("{:p}", std::ptr::invalid::<isize>(val)), exp); } // Escaping diff --git a/library/core/src/iter/adapters/chain.rs b/library/core/src/iter/adapters/chain.rs index 53e48500e3b..60eb3a6da3a 100644 --- a/library/core/src/iter/adapters/chain.rs +++ b/library/core/src/iter/adapters/chain.rs @@ -37,33 +37,6 @@ impl<A, B> Chain<A, B> { } } -/// Fuse the iterator if the expression is `None`. -macro_rules! fuse { - ($self:ident . $iter:ident . $($call:tt)+) => { - match $self.$iter { - Some(ref mut iter) => match iter.$($call)+ { - None => { - $self.$iter = None; - None - } - item => item, - }, - None => None, - } - }; -} - -/// Try an iterator method without fusing, -/// like an inline `.as_mut().and_then(...)` -macro_rules! maybe { - ($self:ident . $iter:ident . $($call:tt)+) => { - match $self.$iter { - Some(ref mut iter) => iter.$($call)+, - None => None, - } - }; -} - #[stable(feature = "rust1", since = "1.0.0")] impl<A, B> Iterator for Chain<A, B> where @@ -74,10 +47,7 @@ where #[inline] fn next(&mut self) -> Option<A::Item> { - match fuse!(self.a.next()) { - None => maybe!(self.b.next()), - item => item, - } + and_then_or_clear(&mut self.a, Iterator::next).or_else(|| self.b.as_mut()?.next()) } #[inline] @@ -161,7 +131,7 @@ where self.a = None; } - maybe!(self.b.nth(n)) + self.b.as_mut()?.nth(n) } #[inline] @@ -169,23 +139,15 @@ where where P: FnMut(&Self::Item) -> bool, { - match fuse!(self.a.find(&mut predicate)) { - None => maybe!(self.b.find(predicate)), - item => item, - } + and_then_or_clear(&mut self.a, |a| a.find(&mut predicate)) + .or_else(|| self.b.as_mut()?.find(predicate)) } #[inline] fn last(self) -> Option<A::Item> { // Must exhaust a before b. - let a_last = match self.a { - Some(a) => a.last(), - None => None, - }; - let b_last = match self.b { - Some(b) => b.last(), - None => None, - }; + let a_last = self.a.and_then(Iterator::last); + let b_last = self.b.and_then(Iterator::last); b_last.or(a_last) } @@ -220,10 +182,7 @@ where { #[inline] fn next_back(&mut self) -> Option<A::Item> { - match fuse!(self.b.next_back()) { - None => maybe!(self.a.next_back()), - item => item, - } + and_then_or_clear(&mut self.b, |b| b.next_back()).or_else(|| self.a.as_mut()?.next_back()) } #[inline] @@ -263,7 +222,7 @@ where self.b = None; } - maybe!(self.a.nth_back(n)) + self.a.as_mut()?.nth_back(n) } #[inline] @@ -271,10 +230,8 @@ where where P: FnMut(&Self::Item) -> bool, { - match fuse!(self.b.rfind(&mut predicate)) { - None => maybe!(self.a.rfind(predicate)), - item => item, - } + and_then_or_clear(&mut self.b, |b| b.rfind(&mut predicate)) + .or_else(|| self.a.as_mut()?.rfind(predicate)) } fn try_rfold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R @@ -324,3 +281,12 @@ where B: TrustedLen<Item = A::Item>, { } + +#[inline] +fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> { + let x = f(opt.as_mut()?); + if x.is_none() { + *opt = None; + } + x +} diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index 351fd569d8a..15a120e35a2 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -290,20 +290,11 @@ where #[inline] fn next(&mut self) -> Option<U::Item> { loop { - if let Some(ref mut inner) = self.frontiter { - match inner.next() { - None => self.frontiter = None, - elt @ Some(_) => return elt, - } + if let elt @ Some(_) = and_then_or_clear(&mut self.frontiter, Iterator::next) { + return elt; } match self.iter.next() { - None => match self.backiter.as_mut()?.next() { - None => { - self.backiter = None; - return None; - } - elt @ Some(_) => return elt, - }, + None => return and_then_or_clear(&mut self.backiter, Iterator::next), Some(inner) => self.frontiter = Some(inner.into_iter()), } } @@ -436,21 +427,12 @@ where #[inline] fn next_back(&mut self) -> Option<U::Item> { loop { - if let Some(ref mut inner) = self.backiter { - match inner.next_back() { - None => self.backiter = None, - elt @ Some(_) => return elt, - } + if let elt @ Some(_) = and_then_or_clear(&mut self.backiter, |b| b.next_back()) { + return elt; } match self.iter.next_back() { - None => match self.frontiter.as_mut()?.next_back() { - None => { - self.frontiter = None; - return None; - } - elt @ Some(_) => return elt, - }, - next => self.backiter = next.map(IntoIterator::into_iter), + None => return and_then_or_clear(&mut self.frontiter, |f| f.next_back()), + Some(inner) => self.backiter = Some(inner.into_iter()), } } } @@ -606,3 +588,12 @@ unsafe impl<T, const N: usize> TrustedConstSize for [T; N] {} unsafe impl<T, const N: usize> TrustedConstSize for &'_ [T; N] {} #[unstable(feature = "std_internals", issue = "none")] unsafe impl<T, const N: usize> TrustedConstSize for &'_ mut [T; N] {} + +#[inline] +fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> { + let x = f(opt.as_mut()?); + if x.is_none() { + *opt = None; + } + x +} diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs index 8adb53c6714..c9314454203 100644 --- a/library/core/src/iter/adapters/fuse.rs +++ b/library/core/src/iter/adapters/fuse.rs @@ -29,33 +29,6 @@ impl<I> Fuse<I> { #[stable(feature = "fused", since = "1.26.0")] impl<I> FusedIterator for Fuse<I> where I: Iterator {} -/// Fuse the iterator if the expression is `None`. -macro_rules! fuse { - ($self:ident . iter . $($call:tt)+) => { - match $self.iter { - Some(ref mut iter) => match iter.$($call)+ { - None => { - $self.iter = None; - None - } - item => item, - }, - None => None, - } - }; -} - -/// Specialized macro that doesn't check if the expression is `None`. -/// (We trust that a `FusedIterator` will fuse itself.) -macro_rules! spec { - ($self:ident . iter . $($call:tt)+) => { - match $self.iter { - Some(ref mut iter) => iter.$($call)+, - None => None, - } - }; -} - // Any specialized implementation here is made internal // to avoid exposing default fns outside this trait. #[stable(feature = "rust1", since = "1.0.0")] @@ -281,12 +254,12 @@ where #[inline] default fn next(&mut self) -> Option<<I as Iterator>::Item> { - fuse!(self.iter.next()) + and_then_or_clear(&mut self.iter, Iterator::next) } #[inline] default fn nth(&mut self, n: usize) -> Option<I::Item> { - fuse!(self.iter.nth(n)) + and_then_or_clear(&mut self.iter, |iter| iter.nth(n)) } #[inline] @@ -308,7 +281,7 @@ where where P: FnMut(&Self::Item) -> bool, { - fuse!(self.iter.find(predicate)) + and_then_or_clear(&mut self.iter, |iter| iter.find(predicate)) } #[inline] @@ -316,7 +289,7 @@ where where I: DoubleEndedIterator, { - fuse!(self.iter.next_back()) + and_then_or_clear(&mut self.iter, |iter| iter.next_back()) } #[inline] @@ -324,7 +297,7 @@ where where I: DoubleEndedIterator, { - fuse!(self.iter.nth_back(n)) + and_then_or_clear(&mut self.iter, |iter| iter.nth_back(n)) } #[inline] @@ -348,7 +321,7 @@ where P: FnMut(&Self::Item) -> bool, I: DoubleEndedIterator, { - fuse!(self.iter.rfind(predicate)) + and_then_or_clear(&mut self.iter, |iter| iter.rfind(predicate)) } } @@ -361,12 +334,12 @@ where { #[inline] fn next(&mut self) -> Option<<I as Iterator>::Item> { - spec!(self.iter.next()) + self.iter.as_mut()?.next() } #[inline] fn nth(&mut self, n: usize) -> Option<I::Item> { - spec!(self.iter.nth(n)) + self.iter.as_mut()?.nth(n) } #[inline] @@ -387,7 +360,7 @@ where where P: FnMut(&Self::Item) -> bool, { - spec!(self.iter.find(predicate)) + self.iter.as_mut()?.find(predicate) } #[inline] @@ -395,7 +368,7 @@ where where I: DoubleEndedIterator, { - spec!(self.iter.next_back()) + self.iter.as_mut()?.next_back() } #[inline] @@ -403,7 +376,7 @@ where where I: DoubleEndedIterator, { - spec!(self.iter.nth_back(n)) + self.iter.as_mut()?.nth_back(n) } #[inline] @@ -426,6 +399,15 @@ where P: FnMut(&Self::Item) -> bool, I: DoubleEndedIterator, { - spec!(self.iter.rfind(predicate)) + self.iter.as_mut()?.rfind(predicate) + } +} + +#[inline] +fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> { + let x = f(opt.as_mut()?); + if x.is_none() { + *opt = None; } + x } diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index e570d831cc6..92d03b724b4 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -213,7 +213,7 @@ macro_rules! nonzero_leading_trailing_zeros { without modifying the original"] #[inline] pub const fn leading_zeros(self) -> u32 { - // SAFETY: since `self` can not be zero it is safe to call ctlz_nonzero + // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`. unsafe { intrinsics::ctlz_nonzero(self.0 as $Uint) as u32 } } @@ -237,7 +237,7 @@ macro_rules! nonzero_leading_trailing_zeros { without modifying the original"] #[inline] pub const fn trailing_zeros(self) -> u32 { - // SAFETY: since `self` can not be zero it is safe to call cttz_nonzero + // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`. unsafe { intrinsics::cttz_nonzero(self.0 as $Uint) as u32 } } diff --git a/library/core/tests/alloc.rs b/library/core/tests/alloc.rs index 6762c0319e5..8a5a06b3440 100644 --- a/library/core/tests/alloc.rs +++ b/library/core/tests/alloc.rs @@ -1,5 +1,5 @@ use core::alloc::Layout; -use core::ptr::NonNull; +use core::ptr::{self, NonNull}; #[test] fn const_unchecked_layout() { @@ -9,7 +9,7 @@ fn const_unchecked_layout() { const DANGLING: NonNull<u8> = LAYOUT.dangling(); assert_eq!(LAYOUT.size(), SIZE); assert_eq!(LAYOUT.align(), ALIGN); - assert_eq!(Some(DANGLING), NonNull::new(ALIGN as *mut u8)); + assert_eq!(Some(DANGLING), NonNull::new(ptr::invalid_mut(ALIGN))); } #[test] diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs index 5bc6aac1778..f7934d062a3 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -2,6 +2,7 @@ mod sip; use std::default::Default; use std::hash::{BuildHasher, Hash, Hasher}; +use std::ptr; use std::rc::Rc; struct MyHasher { @@ -69,10 +70,10 @@ fn test_writer_hasher() { let cs: Rc<[u8]> = Rc::new([1, 2, 3]); assert_eq!(hash(&cs), 9); - let ptr = 5_usize as *const i32; + let ptr = ptr::invalid::<i32>(5_usize); assert_eq!(hash(&ptr), 5); - let ptr = 5_usize as *mut i32; + let ptr = ptr::invalid_mut::<i32>(5_usize); assert_eq!(hash(&ptr), 5); if cfg!(miri) { diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index 3e2956eac87..187a7db7fcb 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -353,9 +353,9 @@ fn align_offset_zst() { // all, because no amount of elements will align the pointer. let mut p = 1; while p < 1024 { - assert_eq!((p as *const ()).align_offset(p), 0); + assert_eq!(ptr::invalid::<()>(p).align_offset(p), 0); if p != 1 { - assert_eq!(((p + 1) as *const ()).align_offset(p), !0); + assert_eq!(ptr::invalid::<()>(p + 1).align_offset(p), !0); } p = (p + 1).next_power_of_two(); } @@ -371,7 +371,7 @@ fn align_offset_stride1() { let expected = ptr % align; let offset = if expected == 0 { 0 } else { align - expected }; assert_eq!( - (ptr as *const u8).align_offset(align), + ptr::invalid::<u8>(ptr).align_offset(align), offset, "ptr = {}, align = {}, size = 1", ptr, @@ -434,14 +434,14 @@ fn align_offset_weird_strides() { while align < limit { for ptr in 1usize..4 * align { unsafe { - x |= test_weird_stride::<A3>(ptr as *const A3, align); - x |= test_weird_stride::<A4>(ptr as *const A4, align); - x |= test_weird_stride::<A5>(ptr as *const A5, align); - x |= test_weird_stride::<A6>(ptr as *const A6, align); - x |= test_weird_stride::<A7>(ptr as *const A7, align); - x |= test_weird_stride::<A8>(ptr as *const A8, align); - x |= test_weird_stride::<A9>(ptr as *const A9, align); - x |= test_weird_stride::<A10>(ptr as *const A10, align); + x |= test_weird_stride::<A3>(ptr::invalid::<A3>(ptr), align); + x |= test_weird_stride::<A4>(ptr::invalid::<A4>(ptr), align); + x |= test_weird_stride::<A5>(ptr::invalid::<A5>(ptr), align); + x |= test_weird_stride::<A6>(ptr::invalid::<A6>(ptr), align); + x |= test_weird_stride::<A7>(ptr::invalid::<A7>(ptr), align); + x |= test_weird_stride::<A8>(ptr::invalid::<A8>(ptr), align); + x |= test_weird_stride::<A9>(ptr::invalid::<A9>(ptr), align); + x |= test_weird_stride::<A10>(ptr::invalid::<A10>(ptr), align); } } align = (align + 1).next_power_of_two(); @@ -479,8 +479,8 @@ fn ptr_metadata() { let () = metadata(&[4, 7]); let () = metadata(&(4, String::new())); let () = metadata(&Pair(4, String::new())); - let () = metadata(0 as *const Extern); - let () = metadata(0 as *const <&u32 as std::ops::Deref>::Target); + let () = metadata(ptr::null::<()>() as *const Extern); + let () = metadata(ptr::null::<()>() as *const <&u32 as std::ops::Deref>::Target); assert_eq!(metadata("foo"), 3_usize); assert_eq!(metadata(&[4, 7][..]), 2_usize); diff --git a/library/core/tests/waker.rs b/library/core/tests/waker.rs index 6602ab36ba7..38a3a0adad9 100644 --- a/library/core/tests/waker.rs +++ b/library/core/tests/waker.rs @@ -3,7 +3,7 @@ use std::task::{RawWaker, RawWakerVTable, Waker}; #[test] fn test_waker_getters() { - let raw_waker = RawWaker::new(42usize as *mut (), &WAKER_VTABLE); + let raw_waker = RawWaker::new(ptr::invalid_mut(42usize), &WAKER_VTABLE); assert_eq!(raw_waker.data() as usize, 42); assert!(ptr::eq(raw_waker.vtable(), &WAKER_VTABLE)); @@ -15,7 +15,7 @@ fn test_waker_getters() { } static WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new( - |data| RawWaker::new((data as usize + 1) as *mut (), &WAKER_VTABLE), + |data| RawWaker::new(ptr::invalid_mut(data as usize + 1), &WAKER_VTABLE), |_| {}, |_| {}, |_| {}, diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index 0ce6ae00ee2..f3fbfc44789 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -396,38 +396,99 @@ fn slice_write_vectored( Ok(nwritten) } -// Resizing write implementation -fn vec_write<A>(pos_mut: &mut u64, vec: &mut Vec<u8, A>, buf: &[u8]) -> io::Result<usize> -where - A: Allocator, -{ +/// Reserves the required space, and pads the vec with 0s if necessary. +fn reserve_and_pad<A: Allocator>( + pos_mut: &mut u64, + vec: &mut Vec<u8, A>, + buf_len: usize, +) -> io::Result<usize> { let pos: usize = (*pos_mut).try_into().map_err(|_| { io::const_io_error!( ErrorKind::InvalidInput, "cursor position exceeds maximum possible vector length", ) })?; - // Make sure the internal buffer is as least as big as where we - // currently are - let len = vec.len(); - if len < pos { - // use `resize` so that the zero filling is as efficient as possible - vec.resize(pos, 0); - } - // Figure out what bytes will be used to overwrite what's currently - // there (left), and what will be appended on the end (right) - { - let space = vec.len() - pos; - let (left, right) = buf.split_at(cmp::min(space, buf.len())); - vec[pos..pos + left.len()].copy_from_slice(left); - vec.extend_from_slice(right); + + // For safety reasons, we don't want these numbers to overflow + // otherwise our allocation won't be enough + let desired_cap = pos.saturating_add(buf_len); + if desired_cap > vec.capacity() { + // We want our vec's total capacity + // to have room for (pos+buf_len) bytes. Reserve allocates + // based on additional elements from the length, so we need to + // reserve the difference + vec.reserve(desired_cap - vec.len()); + } + // Pad if pos is above the current len. + if pos > vec.len() { + let diff = pos - vec.len(); + // Unfortunately, `resize()` would suffice but the optimiser does not + // realise the `reserve` it does can be eliminated. So we do it manually + // to eliminate that extra branch + let spare = vec.spare_capacity_mut(); + debug_assert!(spare.len() >= diff); + // Safety: we have allocated enough capacity for this. + // And we are only writing, not reading + unsafe { + spare.get_unchecked_mut(..diff).fill(core::mem::MaybeUninit::new(0)); + vec.set_len(pos); + } } + Ok(pos) +} + +/// Writes the slice to the vec without allocating +/// # Safety: vec must have buf.len() spare capacity +unsafe fn vec_write_unchecked<A>(pos: usize, vec: &mut Vec<u8, A>, buf: &[u8]) -> usize +where + A: Allocator, +{ + debug_assert!(vec.capacity() >= pos + buf.len()); + vec.as_mut_ptr().add(pos).copy_from(buf.as_ptr(), buf.len()); + pos + buf.len() +} + +/// Resizing write implementation for [`Cursor`] +/// +/// Cursor is allowed to have a pre-allocated and initialised +/// vector body, but with a position of 0. This means the [`Write`] +/// will overwrite the contents of the vec. +/// +/// This also allows for the vec body to be empty, but with a position of N. +/// This means that [`Write`] will pad the vec with 0 initially, +/// before writing anything from that point +fn vec_write<A>(pos_mut: &mut u64, vec: &mut Vec<u8, A>, buf: &[u8]) -> io::Result<usize> +where + A: Allocator, +{ + let buf_len = buf.len(); + let mut pos = reserve_and_pad(pos_mut, vec, buf_len)?; + + // Write the buf then progress the vec forward if necessary + // Safety: we have ensured that the capacity is available + // and that all bytes get written up to pos + unsafe { + pos = vec_write_unchecked(pos, vec, buf); + if pos > vec.len() { + vec.set_len(pos); + } + }; + // Bump us forward - *pos_mut = (pos + buf.len()) as u64; - Ok(buf.len()) + *pos_mut += buf_len as u64; + Ok(buf_len) } +/// Resizing write_vectored implementation for [`Cursor`] +/// +/// Cursor is allowed to have a pre-allocated and initialised +/// vector body, but with a position of 0. This means the [`Write`] +/// will overwrite the contents of the vec. +/// +/// This also allows for the vec body to be empty, but with a position of N. +/// This means that [`Write`] will pad the vec with 0 initially, +/// before writing anything from that point fn vec_write_vectored<A>( pos_mut: &mut u64, vec: &mut Vec<u8, A>, @@ -436,11 +497,26 @@ fn vec_write_vectored<A>( where A: Allocator, { - let mut nwritten = 0; - for buf in bufs { - nwritten += vec_write(pos_mut, vec, buf)?; + // For safety reasons, we don't want this sum to overflow ever. + // If this saturates, the reserve should panic to avoid any unsound writing. + let buf_len = bufs.iter().fold(0usize, |a, b| a.saturating_add(b.len())); + let mut pos = reserve_and_pad(pos_mut, vec, buf_len)?; + + // Write the buf then progress the vec forward if necessary + // Safety: we have ensured that the capacity is available + // and that all bytes get written up to the last pos + unsafe { + for buf in bufs { + pos = vec_write_unchecked(pos, vec, buf); + } + if pos > vec.len() { + vec.set_len(pos); + } } - Ok(nwritten) + + // Bump us forward + *pos_mut += buf_len as u64; + Ok(buf_len) } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/io/cursor/tests.rs b/library/std/src/io/cursor/tests.rs index f1ee177b7f3..d7c203c297f 100644 --- a/library/std/src/io/cursor/tests.rs +++ b/library/std/src/io/cursor/tests.rs @@ -20,6 +20,7 @@ fn test_vec_writer() { #[test] fn test_mem_writer() { let mut writer = Cursor::new(Vec::new()); + writer.set_position(10); assert_eq!(writer.write(&[0]).unwrap(), 1); assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); @@ -30,6 +31,17 @@ fn test_mem_writer() { 3 ); let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(&writer.get_ref()[..10], &[0; 10]); + assert_eq!(&writer.get_ref()[10..], b); +} + +#[test] +fn test_mem_writer_preallocated() { + let mut writer = Cursor::new(vec![0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 10]); + assert_eq!(writer.write(&[0]).unwrap(), 1); + assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); + assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); + let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; assert_eq!(&writer.get_ref()[..], b); } @@ -517,3 +529,39 @@ fn const_cursor() { const _: &&[u8] = CURSOR.get_ref(); const _: u64 = CURSOR.position(); } + +#[bench] +fn bench_write_vec(b: &mut test::Bencher) { + let slice = &[1; 128]; + + b.iter(|| { + let mut buf = b"some random data to overwrite".to_vec(); + let mut cursor = Cursor::new(&mut buf); + + let _ = cursor.write_all(slice); + test::black_box(&cursor); + }) +} + +#[bench] +fn bench_write_vec_vectored(b: &mut test::Bencher) { + let slices = [ + IoSlice::new(&[1; 128]), + IoSlice::new(&[2; 256]), + IoSlice::new(&[3; 512]), + IoSlice::new(&[4; 1024]), + IoSlice::new(&[5; 2048]), + IoSlice::new(&[6; 4096]), + IoSlice::new(&[7; 8192]), + IoSlice::new(&[8; 8192 * 2]), + ]; + + b.iter(|| { + let mut buf = b"some random data to overwrite".to_vec(); + let mut cursor = Cursor::new(&mut buf); + + let mut slices = slices; + let _ = cursor.write_all_vectored(&mut slices); + test::black_box(&cursor); + }) +} diff --git a/library/std/src/sys/hermit/condvar.rs b/library/std/src/sys/hermit/condvar.rs index 3f00160e55a..22059ca0dbe 100644 --- a/library/std/src/sys/hermit/condvar.rs +++ b/library/std/src/sys/hermit/condvar.rs @@ -3,6 +3,7 @@ use crate::ptr; use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst}; use crate::sys::hermit::abi; use crate::sys::locks::Mutex; +use crate::sys_common::lazy_box::{LazyBox, LazyInit}; use crate::time::Duration; // The implementation is inspired by Andrew D. Birrell's paper @@ -14,14 +15,26 @@ pub struct Condvar { sem2: *const c_void, } -pub type MovableCondvar = Condvar; +pub(crate) type MovableCondvar = LazyBox<Condvar>; + +impl LazyInit for Condvar { + fn init() -> Box<Self> { + Box::new(Self::new()) + } +} unsafe impl Send for Condvar {} unsafe impl Sync for Condvar {} impl Condvar { - pub const fn new() -> Condvar { - Condvar { counter: AtomicUsize::new(0), sem1: ptr::null(), sem2: ptr::null() } + pub fn new() -> Self { + let mut condvar = + Self { counter: AtomicUsize::new(0), sem1: ptr::null(), sem2: ptr::null() }; + unsafe { + let _ = abi::sem_init(&mut condvar.sem1, 0); + let _ = abi::sem_init(&mut condvar.sem2, 0); + } + condvar } pub unsafe fn notify_one(&self) { diff --git a/library/std/src/sys/hermit/mutex.rs b/library/std/src/sys/hermit/mutex.rs index ef44bf411fb..eb15a04ffcf 100644 --- a/library/std/src/sys/hermit/mutex.rs +++ b/library/std/src/sys/hermit/mutex.rs @@ -175,9 +175,7 @@ impl Mutex { } #[inline] - pub unsafe fn init(&mut self) { - self.inner = Spinlock::new(MutexInner::new()); - } + pub unsafe fn init(&mut self) {} #[inline] pub unsafe fn lock(&self) { diff --git a/library/std/src/sys/hermit/rwlock.rs b/library/std/src/sys/hermit/rwlock.rs index d43fa08a171..9701bab1f66 100644 --- a/library/std/src/sys/hermit/rwlock.rs +++ b/library/std/src/sys/hermit/rwlock.rs @@ -1,9 +1,10 @@ use crate::cell::UnsafeCell; -use crate::sys::locks::{Condvar, Mutex}; +use crate::sys::locks::{MovableCondvar, Mutex}; +use crate::sys_common::lazy_box::{LazyBox, LazyInit}; pub struct RwLock { lock: Mutex, - cond: Condvar, + cond: MovableCondvar, state: UnsafeCell<State>, } @@ -28,7 +29,11 @@ unsafe impl Sync for RwLock {} impl RwLock { pub const fn new() -> RwLock { - RwLock { lock: Mutex::new(), cond: Condvar::new(), state: UnsafeCell::new(State::Unlocked) } + RwLock { + lock: Mutex::new(), + cond: MovableCondvar::new(), + state: UnsafeCell::new(State::Unlocked), + } } #[inline] diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index ea410849694..9cd8b6d1455 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -160,7 +160,7 @@ pub(crate) fn maybe_download_ci_llvm(builder: &Builder<'_>) { // files in the tarball are in the past, so it doesn't trigger a // rebuild. let now = filetime::FileTime::from_system_time(std::time::SystemTime::now()); - let llvm_config = llvm_root.join("bin/llvm-config"); + let llvm_config = llvm_root.join("bin").join(exe("llvm-config", builder.config.build)); t!(filetime::set_file_times(&llvm_config, now, now)); let llvm_lib = llvm_root.join("lib"); diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index e59324331ae..6e3651665c8 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -6,6 +6,7 @@ use std::path::PathBuf; use std::str::FromStr; use rustc_data_structures::fx::FxHashMap; +use rustc_driver::print_flag_list; use rustc_session::config::{ self, parse_crate_types_from_list, parse_externs, parse_target_triple, CrateType, }; @@ -310,11 +311,15 @@ impl RenderOptions { impl Options { /// Parses the given command-line for options. If an error message or other early-return has /// been printed, returns `Err` with the exit code. - pub(crate) fn from_matches(matches: &getopts::Matches) -> Result<Options, i32> { + pub(crate) fn from_matches( + matches: &getopts::Matches, + args: Vec<String>, + ) -> Result<Options, i32> { + let args = &args[1..]; // Check for unstable options. nightly_options::check_nightly_options(matches, &opts()); - if matches.opt_present("h") || matches.opt_present("help") { + if args.is_empty() || matches.opt_present("h") || matches.opt_present("help") { crate::usage("rustdoc"); return Err(0); } else if matches.opt_present("version") { @@ -335,6 +340,21 @@ impl Options { // check for deprecated options check_deprecated_options(matches, &diag); + let z_flags = matches.opt_strs("Z"); + if z_flags.iter().any(|x| *x == "help") { + print_flag_list("-Z", config::DB_OPTIONS); + return Err(0); + } + let c_flags = matches.opt_strs("C"); + if c_flags.iter().any(|x| *x == "help") { + print_flag_list("-C", config::CG_OPTIONS); + return Err(0); + } + let w_flags = matches.opt_strs("W"); + if w_flags.iter().any(|x| *x == "help") { + print_flag_list("-W", config::DB_OPTIONS); + return Err(0); + } if matches.opt_strs("passes") == ["list"] { println!("Available passes for running rustdoc:"); for pass in passes::PASSES { diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index c627dcc30d6..428519dbc16 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -252,8 +252,11 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { bounds: b.into_iter().map(|x| x.into_tcx(tcx)).collect(), default: None, }, - // FIXME: do not map to Typedef but to a custom variant - AssocTypeItem(t, _) => ItemEnum::Typedef(t.into_tcx(tcx)), + AssocTypeItem(t, b) => ItemEnum::AssocType { + generics: t.generics.into_tcx(tcx), + bounds: b.into_iter().map(|x| x.into_tcx(tcx)).collect(), + default: t.item_type.map(|ty| ty.into_tcx(tcx)), + }, // `convert_item` early returns `None` for striped items and keywords. StrippedItem(_) | KeywordItem(_) => unreachable!(), ExternCrateItem { ref src } => ItemEnum::ExternCrate { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 54b85166041..db4c3d10237 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -686,7 +686,7 @@ fn main_args(at_args: &[String]) -> MainResult { // Note that we discard any distinction between different non-zero exit // codes from `from_matches` here. - let options = match config::Options::from_matches(&matches) { + let options = match config::Options::from_matches(&matches, args) { Ok(opts) => opts, Err(code) => { return if code == 0 { diff --git a/src/llvm-project b/src/llvm-project -Subproject c9e2e89ed3aa5a3be77143aa0c86906b4138374 +Subproject d1ddc34c4b23468f6d2bf553084834b104e16dd diff --git a/src/test/run-make/issue-88756-default-output/Makefile b/src/test/run-make/issue-88756-default-output/Makefile new file mode 100644 index 00000000000..cacbcbf3933 --- /dev/null +++ b/src/test/run-make/issue-88756-default-output/Makefile @@ -0,0 +1,4 @@ +-include ../../run-make-fulldeps/tools.mk + +all: + $(BARE_RUSTDOC) 2>&1 | sed -E 's@/nightly/|/beta/|/stable/|/1\.[0-9]+\.[0-9]+/@/$$CHANNEL/@g' | diff - output-default.stdout diff --git a/src/test/run-make/issue-88756-default-output/README.md b/src/test/run-make/issue-88756-default-output/README.md new file mode 100644 index 00000000000..8cbfac4f7d2 --- /dev/null +++ b/src/test/run-make/issue-88756-default-output/README.md @@ -0,0 +1 @@ +This is a test to verify that the default behavior of `rustdoc` is printing out help output instead of erroring out (#88756). diff --git a/src/test/run-make/issue-88756-default-output/output-default.stdout b/src/test/run-make/issue-88756-default-output/output-default.stdout new file mode 100644 index 00000000000..6d16fe5673b --- /dev/null +++ b/src/test/run-make/issue-88756-default-output/output-default.stdout @@ -0,0 +1,193 @@ +rustdoc [options] <input> + +Options: + -h, --help show this help message + -V, --version print rustdoc's version + -v, --verbose use verbose output + -w, --output-format [html] + the output type to write + --output PATH Which directory to place the output. This option is + deprecated, use --out-dir instead. + -o, --out-dir PATH which directory to place the output + --crate-name NAME + specify the name of this crate + --crate-type [bin|lib|rlib|dylib|cdylib|staticlib|proc-macro] + Comma separated list of types of crates + for the compiler to emit + -L, --library-path DIR + directory to add to crate search path + --cfg pass a --cfg to rustc + --check-cfg pass a --check-cfg to rustc + --extern NAME[=PATH] + pass an --extern to rustc + --extern-html-root-url NAME=URL + base URL to use for dependencies; for example, + "std=/doc" links std::vec::Vec to + /doc/std/vec/struct.Vec.html + --extern-html-root-takes-precedence + give precedence to `--extern-html-root-url`, not + `html_root_url` + -C, --codegen OPT[=VALUE] + pass a codegen option to rustc + --document-private-items + document private items + --document-hidden-items + document items that have doc(hidden) + --test run code examples as tests + --test-args ARGS + arguments to pass to the test runner + --test-run-directory PATH + The working directory in which to run tests + --target TRIPLE target triple to document + --markdown-css FILES + CSS files to include via <link> in a rendered Markdown + file + --html-in-header FILES + files to include inline in the <head> section of a + rendered Markdown file or generated documentation + --html-before-content FILES + files to include inline between <body> and the content + of a rendered Markdown file or generated documentation + --html-after-content FILES + files to include inline between the content and + </body> of a rendered Markdown file or generated + documentation + --markdown-before-content FILES + files to include inline between <body> and the content + of a rendered Markdown file or generated documentation + --markdown-after-content FILES + files to include inline between the content and + </body> of a rendered Markdown file or generated + documentation + --markdown-playground-url URL + URL to send code snippets to + --markdown-no-toc + don't include table of contents + -e, --extend-css PATH + To add some CSS rules with a given file to generate + doc with your own theme. However, your theme might + break if the rustdoc's generated HTML changes, so be + careful! + -Z FLAG internal and debugging options (only on nightly build) + --sysroot PATH Override the system root + --playground-url URL + URL to send code snippets to, may be reset by + --markdown-playground-url or + `#![doc(html_playground_url=...)]` + --display-doctest-warnings + show warnings that originate in doctests + --crate-version VERSION + crate version to print into documentation + --sort-modules-by-appearance + sort modules by where they appear in the program, + rather than alphabetically + --default-theme THEME + Set the default theme. THEME should be the theme name, + generally lowercase. If an unknown default theme is + specified, the builtin default is used. The set of + themes, and the rustdoc built-in default, are not + stable. + --default-setting SETTING[=VALUE] + Default value for a rustdoc setting (used when + "rustdoc-SETTING" is absent from web browser Local + Storage). If VALUE is not supplied, "true" is used. + Supported SETTINGs and VALUEs are not documented and + not stable. + --theme FILES additional themes which will be added to the generated + docs + --check-theme FILES + check if given theme is valid + --resource-suffix PATH + suffix to add to CSS and JavaScript files, e.g., + "light.css" will become "light-suffix.css" + --edition EDITION + edition to use when compiling rust code (default: + 2015) + --color auto|always|never + Configure coloring of output: + auto = colorize, if output goes to a tty (default); + always = always colorize output; + never = never colorize output + --error-format human|json|short + How errors and other messages are produced + --json CONFIG Configure the structure of JSON diagnostics + --disable-minification + Disable minification applied on JS files + -A, --allow LINT Set lint allowed + -W, --warn LINT Set lint warnings + --force-warn LINT + Set lint force-warn + -D, --deny LINT Set lint denied + -F, --forbid LINT Set lint forbidden + --cap-lints LEVEL + Set the most restrictive lint level. More restrictive + lints are capped at this level. By default, it is at + `forbid` level. + --index-page PATH + Markdown file to be used as index page + --enable-index-page + To enable generation of the index page + --static-root-path PATH + Path string to force loading static files from in + output pages. If not set, uses combinations of '../' + to reach the documentation root. + --disable-per-crate-search + disables generating the crate selector on the search + box + --persist-doctests PATH + Directory to persist doctest executables into + --show-coverage + calculate percentage of public items with + documentation + --enable-per-target-ignores + parse ignore-foo for ignoring doctests on a per-target + basis + --runtool The tool to run tests with when building for a different target than host + + --runtool-arg One (of possibly many) arguments to pass to the runtool + + --test-builder PATH + The rustc-like binary to use as the test builder + --check Run rustdoc checks + --generate-redirect-map + Generate JSON file at the top level instead of + generating HTML redirection files + --emit [unversioned-shared-resources,toolchain-shared-resources,invocation-specific] + Comma separated list of types of output for rustdoc to + emit + --no-run Compile doctests without running them + --show-type-layout + Include the memory layout of types in the docs + --nocapture Don't capture stdout and stderr of tests + --generate-link-to-definition + Make the identifiers in the HTML source code pages + navigable + --scrape-examples-output-path collect function call information and output at the given path + + --scrape-examples-target-crate collect function call information for functions from the target crate + + --scrape-tests Include test code when scraping examples + --with-examples path to function call information (for displaying examples in the documentation) + + --plugin-path DIR + removed, see issue #44136 + <https://github.com/rust-lang/rust/issues/44136> for + more information + --passes PASSES removed, see issue #44136 + <https://github.com/rust-lang/rust/issues/44136> for + more information + --plugins PLUGINS + removed, see issue #44136 + <https://github.com/rust-lang/rust/issues/44136> for + more information + --no-defaults removed, see issue #44136 + <https://github.com/rust-lang/rust/issues/44136> for + more information + -r, --input-format [rust] + removed, see issue #44136 + <https://github.com/rust-lang/rust/issues/44136> for + more information + + @path Read newline separated options from `path` + +More information available at https://doc.rust-lang.org/$CHANNEL/rustdoc/what-is-rustdoc.html diff --git a/src/test/run-make/issue-88756-default-output/x.rs b/src/test/run-make/issue-88756-default-output/x.rs new file mode 100644 index 00000000000..5df7576133a --- /dev/null +++ b/src/test/run-make/issue-88756-default-output/x.rs @@ -0,0 +1 @@ +// nothing to see here diff --git a/src/test/run-make/issue-88756-opt-help/Makefile b/src/test/run-make/issue-88756-opt-help/Makefile new file mode 100644 index 00000000000..8ababbf5b4e --- /dev/null +++ b/src/test/run-make/issue-88756-opt-help/Makefile @@ -0,0 +1,4 @@ +-include ../../run-make-fulldeps/tools.mk + +all: + $(RUSTDOC) -W help 2>&1 | diff - output-default.stdout diff --git a/src/test/run-make/issue-88756-opt-help/README.md b/src/test/run-make/issue-88756-opt-help/README.md new file mode 100644 index 00000000000..9b742753f25 --- /dev/null +++ b/src/test/run-make/issue-88756-opt-help/README.md @@ -0,0 +1 @@ +This is a test to verify that `rustdoc` behaves the same as rustc and prints out help output for its options like -W (#88756). diff --git a/src/test/run-make/issue-88756-opt-help/output-default.stdout b/src/test/run-make/issue-88756-opt-help/output-default.stdout new file mode 100644 index 00000000000..5cb7ecb649a --- /dev/null +++ b/src/test/run-make/issue-88756-opt-help/output-default.stdout @@ -0,0 +1,193 @@ + -W allow-features=val -- only allow the listed language features to be enabled in code (space separated) + -W always-encode-mir=val -- encode MIR of all functions into the crate metadata (default: no) + -W assume-incomplete-release=val -- make cfg(version) treat the current version as incomplete (default: no) + -W asm-comments=val -- generate comments into the assembly (may change behavior) (default: no) + -W assert-incr-state=val -- assert that the incremental cache is in given state: either `loaded` or `not-loaded`. + -W binary-dep-depinfo=val -- include artifacts (sysroot, crate dependencies) used during compilation in dep-info (default: no) + -W branch-protection=val -- set options for branch target identification and pointer authentication on AArch64 + -W cf-protection=val -- instrument control-flow architecture protection + -W cgu-partitioning-strategy=val -- the codegen unit partitioning strategy to use + -W chalk=val -- enable the experimental Chalk-based trait solving engine + -W codegen-backend=val -- the backend to use + -W combine-cgu=val -- combine CGUs into a single one + -W crate-attr=val -- inject the given attribute in the crate + -W debug-info-for-profiling=val -- emit discriminators and other data necessary for AutoFDO + -W debug-macros=val -- emit line numbers debug info inside macros (default: no) + -W deduplicate-diagnostics=val -- deduplicate identical diagnostics (default: yes) + -W dep-info-omit-d-target=val -- in dep-info output, omit targets for tracking dependencies of the dep-info files themselves (default: no) + -W dep-tasks=val -- print tasks that execute and the color their dep node gets (requires debug build) (default: no) + -W dlltool=val -- import library generation tool (windows-gnu only) + -W dont-buffer-diagnostics=val -- emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) (default: no) + -W drop-tracking=val -- enables drop tracking in generators (default: no) + -W dual-proc-macros=val -- load proc macros for both target and host, but only link to the target (default: no) + -W dump-dep-graph=val -- dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv) (default: no) + -W dump-mir=val -- dump MIR state to file. + `val` is used to select which passes and functions to dump. For example: + `all` matches all passes and functions, + `foo` matches all passes for functions whose name contains 'foo', + `foo & ConstProp` only the 'ConstProp' pass for function names containing 'foo', + `foo | bar` all passes for function names containing 'foo' or 'bar'. + -W dump-mir-dataflow=val -- in addition to `.mir` files, create graphviz `.dot` files with dataflow results (default: no) + -W dump-mir-dir=val -- the directory the MIR is dumped into (default: `mir_dump`) + -W dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no) + -W dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no) + -W dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans. + -W emit-stack-sizes=val -- emit a section containing stack size metadata (default: no) + -W fewer-names=val -- reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) (default: no) + -W force-unstable-if-unmarked=val -- force all crates to be `rustc_private` unstable (default: no) + -W fuel=val -- set the optimization fuel quota for a crate + -W function-sections=val -- whether each function should go in its own section + -W future-incompat-test=val -- forces all lints to be future incompatible, used for internal testing (default: no) + -W gcc-ld=val -- implementation of ld used by cc + -W graphviz-dark-mode=val -- use dark-themed colors in graphviz output (default: no) + -W graphviz-font=val -- use the given `fontname` in graphviz output; can be overridden by setting environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`) + -W hir-stats=val -- print some statistics about AST and HIR (default: no) + -W human-readable-cgu-names=val -- generate human-readable, predictable names for codegen units (default: no) + -W identify-regions=val -- display unnamed regions as `'<id>`, using a non-ident unique id (default: no) + -W incremental-ignore-spans=val -- ignore spans during ICH computation -- used for testing (default: no) + -W incremental-info=val -- print high-level information about incremental reuse (or the lack thereof) (default: no) + -W incremental-relative-spans=val -- hash spans relative to their parent item for incr. comp. (default: no) + -W incremental-verify-ich=val -- verify incr. comp. hashes of green query instances (default: no) + -W inline-mir=val -- enable MIR inlining (default: no) + -W inline-mir-threshold=val -- a default MIR inlining threshold (default: 50) + -W inline-mir-hint-threshold=val -- inlining threshold for functions with inline hint (default: 100) + -W inline-in-all-cgus=val -- control whether `#[inline]` functions are in all CGUs + -W input-stats=val -- gather statistics about the input (default: no) + -W instrument-coverage=val -- instrument the generated code to support LLVM source-based code coverage reports (note, the compiler build config must include `profiler = true`); implies `-C symbol-mangling-version=v0`. Optional values are: + `=all` (implicit value) + `=except-unused-generics` + `=except-unused-functions` + `=off` (default) + -W instrument-mcount=val -- insert function instrument code for mcount-based tracing (default: no) + -W keep-hygiene-data=val -- keep hygiene data after analysis (default: no) + -W link-native-libraries=val -- link native libraries in the linker invocation (default: yes) + -W link-only=val -- link the `.rlink` file generated by `-Z no-link` (default: no) + -W llvm-plugins=val -- a list LLVM plugins to enable (space separated) + -W llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no) + -W location-detail=val -- comma separated list of location details to be tracked when using caller_location valid options are `file`, `line`, and `column` (default: all) + -W ls=val -- list the symbols defined by a library crate (default: no) + -W macro-backtrace=val -- show macro backtraces (default: no) + -W merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name + -W meta-stats=val -- gather metadata statistics (default: no) + -W mir-emit-retag=val -- emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 (default: no) + -W mir-enable-passes=val -- use like `-Zmir-enable-passes=+DestProp,-InstCombine`. Forces the specified passes to be enabled, overriding all other checks. Passes that are not specified are enabled or disabled by other flags as usual. + -W mir-opt-level=val -- MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds) + -W move-size-limit=val -- the size at which the `large_assignments` lint starts to be emitted + -W mutable-noalias=val -- emit noalias metadata for mutable references (default: yes) + -W new-llvm-pass-manager=val -- use new LLVM pass manager (default: no) + -W nll-facts=val -- dump facts from NLL analysis into side files (default: no) + -W nll-facts-dir=val -- the directory the NLL facts are dumped into (default: `nll-facts`) + -W no-analysis=val -- parse and expand the source, but run no analysis + -W no-codegen=val -- run all passes except codegen; no output + -W no-generate-arange-section=val -- omit DWARF address ranges that give faster lookups + -W no-interleave-lints=val -- execute lints separately; allows benchmarking individual lints + -W no-leak-check=val -- disable the 'leak check' for subtyping; unsound, but useful for tests + -W no-link=val -- compile without linking + -W no-parallel-llvm=val -- run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO) + -W no-unique-section-names=val -- do not use unique names for text and data sections when -Z function-sections is used + -W no-profiler-runtime=val -- prevent automatic injection of the profiler_builtins crate + -W normalize-docs=val -- normalize associated items in rustdoc when generating documentation + -W oom=val -- panic strategy for out-of-memory handling + -W osx-rpath-install-name=val -- pass `-install_name @rpath/...` to the macOS linker (default: no) + -W panic-abort-tests=val -- support compiling tests with panic=abort (default: no) + -W panic-in-drop=val -- panic strategy for panics in drops + -W parse-only=val -- parse only; do not compile, assemble, or link (default: no) + -W perf-stats=val -- print some performance-related statistics (default: no) + -W pick-stable-methods-before-any-unstable=val -- try to pick stable methods first before picking any unstable methods (default: yes) + -W plt=val -- whether to use the PLT when calling into shared libraries; + only has effect for PIC code on systems with ELF binaries + (default: PLT is disabled if full relro is enabled) + -W polonius=val -- enable polonius-based borrow-checker (default: no) + -W polymorphize=val -- perform polymorphization analysis + -W pre-link-arg=val -- a single extra argument to prepend the linker invocation (can be used several times) + -W pre-link-args=val -- extra arguments to prepend to the linker invocation (space separated) + -W precise-enum-drop-elaboration=val -- use a more precise version of drop elaboration for matches on enums (default: yes). This results in better codegen, but has caused miscompilations on some tier 2 platforms. See #77382 and #74551. + -W print-fuel=val -- make rustc print the total optimization fuel used by a crate + -W print-llvm-passes=val -- print the LLVM optimization passes being run (default: no) + -W print-mono-items=val -- print the result of the monomorphization collection pass + -W print-type-sizes=val -- print layout information for each type encountered (default: no) + -W proc-macro-backtrace=val -- show backtraces for panics during proc-macro execution (default: no) + -W profile=val -- insert profiling code (default: no) + -W profile-closures=val -- profile size of closures + -W profile-emit=val -- file path to emit profiling data at runtime when using 'profile' (default based on relative source path) + -W profiler-runtime=val -- name of the profiler runtime crate to automatically inject (default: `profiler_builtins`) + -W profile-sample-use=val -- use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO) + -W query-dep-graph=val -- enable queries of the dependency graph for regression testing (default: no) + -W randomize-layout=val -- randomize the layout of types (default: no) + -W layout-seed=val -- seed layout randomization + -W relax-elf-relocations=val -- whether ELF relocations can be relaxed + -W relro-level=val -- choose which RELRO level to use + -W remap-cwd-prefix=val -- remap paths under the current working directory to this path prefix + -W simulate-remapped-rust-src-base=val -- simulate the effect of remap-debuginfo = true at bootstrapping by remapping path to rust's source base directory. only meant for testing purposes + -W report-delayed-bugs=val -- immediately print bugs registered with `delay_span_bug` (default: no) + -W sanitizer=val -- use a sanitizer + -W sanitizer-memory-track-origins=val -- enable origins tracking in MemorySanitizer + -W sanitizer-recover=val -- enable recovery for selected sanitizers + -W saturating-float-casts=val -- make float->int casts UB-free: numbers outside the integer type's range are clipped to the max/min integer respectively, and NaN is mapped to 0 (default: yes) + -W save-analysis=val -- write syntax and type analysis (in JSON format) information, in addition to normal output (default: no) + -W self-profile=val -- run the self profiler and output the raw event data + -W self-profile-events=val -- specify the events recorded by the self profiler; + for example: `-Z self-profile-events=default,query-keys` + all options: none, all, default, generic-activity, query-provider, query-cache-hit + query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm, artifact-sizes + -W self-profile-counter=val -- counter used by the self profiler (default: `wall-time`), one of: + `wall-time` (monotonic clock, i.e. `std::time::Instant`) + `instructions:u` (retired instructions, userspace-only) + `instructions-minus-irqs:u` (subtracting hardware interrupt counts for extra accuracy) + -W share-generics=val -- make the current crate share its generic instantiations + -W show-span=val -- show spans for compiler debugging (expr|pat|ty) + -W span-debug=val -- forward proc_macro::Span's `Debug` impl to `Span` + -W span-free-formats=val -- exclude spans when debug-printing compiler state (default: no) + -W src-hash-algorithm=val -- hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`) + -W stack-protector=val -- control stack smash protection strategy (`rustc --print stack-protector-strategies` for details) + -W strict-init-checks=val -- control if mem::uninitialized and mem::zeroed panic on more UB + -W strip=val -- tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`) + -W split-dwarf-kind=val -- split dwarf variant (only if -Csplit-debuginfo is enabled and on relevant platform) + (default: `split`) + + `split`: sections which do not require relocation are written into a DWARF object (`.dwo`) + file which is ignored by the linker + `single`: sections which do not require relocation are written into object file but ignored + by the linker + -W split-dwarf-inlining=val -- provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF + -W symbol-mangling-version=val -- which mangling version to use for symbol names ('legacy' (default) or 'v0') + -W teach=val -- show extended diagnostic help (default: no) + -W temps-dir=val -- the directory the intermediate files are written to + -W terminal-width=val -- set the current terminal width + -W translate-lang=val -- language identifier for diagnostic output + -W translate-additional-ftl=val -- additional fluent translation to preferentially use (for testing translation) + -W translate-directionality-markers=val -- emit directionality isolation markers in translated diagnostics + -W tune-cpu=val -- select processor to schedule for (`rustc --print target-cpus` for details) + -W thinlto=val -- enable ThinLTO when possible + -W thir-unsafeck=val -- use the THIR unsafety checker (default: no) + -W threads=val -- use a thread pool with N threads + -W time=val -- measure time of rustc processes (default: no) + -W time-llvm-passes=val -- measure time of each LLVM pass (default: no) + -W time-passes=val -- measure time of each rustc pass (default: no) + -W tls-model=val -- choose the TLS model to use (`rustc --print tls-models` for details) + -W trace-macros=val -- for every macro invocation, print its name and arguments (default: no) + -W translate-remapped-path-to-local-path=val -- translate remapped paths into local paths when possible (default: yes) + -W trap-unreachable=val -- generate trap instructions for unreachable intrinsics (default: use target setting, usually yes) + -W treat-err-as-bug=val -- treat error number `val` that occurs as bug + -W trim-diagnostic-paths=val -- in diagnostics, use heuristics to shorten paths referring to items + -W ui-testing=val -- emit compiler diagnostics in a form suitable for UI testing (default: no) + -W uninit-const-chunk-threshold=val -- allow generating const initializers with mixed init/uninit chunks, and set the maximum number of chunks for which this is allowed (default: 16) + -W unleash-the-miri-inside-of-you=val -- take the brakes off const evaluation. NOTE: this is unsound (default: no) + -W unpretty=val -- present the input source, unstable (and less-pretty) variants; + `normal`, `identified`, + `expanded`, `expanded,identified`, + `expanded,hygiene` (with internal representations), + `ast-tree` (raw AST before expansion), + `ast-tree,expanded` (raw AST after expansion), + `hir` (the HIR), `hir,identified`, + `hir,typed` (HIR with types for each node), + `hir-tree` (dump the raw HIR), + `mir` (the MIR), or `mir-cfg` (graphviz formatted MIR) + -W unsound-mir-opts=val -- enable unsound and buggy MIR optimizations (default: no) + -W unstable-options=val -- adds unstable command line options to rustc interface (default: no) + -W use-ctors-section=val -- use legacy .ctors section for initializers rather than .init_array + -W validate-mir=val -- validate MIR after each transformation + -W verbose=val -- in general, enable more debug printouts (default: no) + -W verify-llvm-ir=val -- verify LLVM IR (default: no) + -W virtual-function-elimination=val -- enables dead virtual function elimination optimization. Requires `-Clto[=[fat,yes]]` + -W wasi-exec-model=val -- whether to build a wasi command or reactor diff --git a/src/test/run-make/issue-88756-opt-help/x.rs b/src/test/run-make/issue-88756-opt-help/x.rs new file mode 100644 index 00000000000..5df7576133a --- /dev/null +++ b/src/test/run-make/issue-88756-opt-help/x.rs @@ -0,0 +1 @@ +// nothing to see here diff --git a/src/test/rustdoc-json/assoc_items.rs b/src/test/rustdoc-json/assoc_items.rs new file mode 100644 index 00000000000..2ee64c9f6eb --- /dev/null +++ b/src/test/rustdoc-json/assoc_items.rs @@ -0,0 +1,29 @@ +#![no_std] + +// @has assoc_items.json + +pub struct Simple; + +impl Simple { + // @has - "$.index[*][?(@.name=='CONSTANT')].kind" \"assoc_const\" + pub const CONSTANT: usize = 0; +} + +pub trait EasyToImpl { + // @has - "$.index[*][?(@.name=='ToDeclare')].kind" \"assoc_type\" + // @has - "$.index[*][?(@.name=='ToDeclare')].inner.default" null + type ToDeclare; + // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].kind" \"assoc_const\" + // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.default" null + const AN_ATTRIBUTE: usize; +} + +impl EasyToImpl for Simple { + // @has - "$.index[*][?(@.name=='ToDeclare')].inner.default.kind" \"primitive\" + // @has - "$.index[*][?(@.name=='ToDeclare')].inner.default.inner" \"usize\" + type ToDeclare = usize; + // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.type.kind" \"primitive\" + // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.type.inner" \"usize\" + // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.default" \"12\" + const AN_ATTRIBUTE: usize = 12; +} diff --git a/src/test/rustdoc-ui/issue-83883-describe-lints.stdout b/src/test/rustdoc-ui/issue-83883-describe-lints.stdout index 651faf5761f..5cb7ecb649a 100644 --- a/src/test/rustdoc-ui/issue-83883-describe-lints.stdout +++ b/src/test/rustdoc-ui/issue-83883-describe-lints.stdout @@ -1,25 +1,193 @@ + -W allow-features=val -- only allow the listed language features to be enabled in code (space separated) + -W always-encode-mir=val -- encode MIR of all functions into the crate metadata (default: no) + -W assume-incomplete-release=val -- make cfg(version) treat the current version as incomplete (default: no) + -W asm-comments=val -- generate comments into the assembly (may change behavior) (default: no) + -W assert-incr-state=val -- assert that the incremental cache is in given state: either `loaded` or `not-loaded`. + -W binary-dep-depinfo=val -- include artifacts (sysroot, crate dependencies) used during compilation in dep-info (default: no) + -W branch-protection=val -- set options for branch target identification and pointer authentication on AArch64 + -W cf-protection=val -- instrument control-flow architecture protection + -W cgu-partitioning-strategy=val -- the codegen unit partitioning strategy to use + -W chalk=val -- enable the experimental Chalk-based trait solving engine + -W codegen-backend=val -- the backend to use + -W combine-cgu=val -- combine CGUs into a single one + -W crate-attr=val -- inject the given attribute in the crate + -W debug-info-for-profiling=val -- emit discriminators and other data necessary for AutoFDO + -W debug-macros=val -- emit line numbers debug info inside macros (default: no) + -W deduplicate-diagnostics=val -- deduplicate identical diagnostics (default: yes) + -W dep-info-omit-d-target=val -- in dep-info output, omit targets for tracking dependencies of the dep-info files themselves (default: no) + -W dep-tasks=val -- print tasks that execute and the color their dep node gets (requires debug build) (default: no) + -W dlltool=val -- import library generation tool (windows-gnu only) + -W dont-buffer-diagnostics=val -- emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) (default: no) + -W drop-tracking=val -- enables drop tracking in generators (default: no) + -W dual-proc-macros=val -- load proc macros for both target and host, but only link to the target (default: no) + -W dump-dep-graph=val -- dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv) (default: no) + -W dump-mir=val -- dump MIR state to file. + `val` is used to select which passes and functions to dump. For example: + `all` matches all passes and functions, + `foo` matches all passes for functions whose name contains 'foo', + `foo & ConstProp` only the 'ConstProp' pass for function names containing 'foo', + `foo | bar` all passes for function names containing 'foo' or 'bar'. + -W dump-mir-dataflow=val -- in addition to `.mir` files, create graphviz `.dot` files with dataflow results (default: no) + -W dump-mir-dir=val -- the directory the MIR is dumped into (default: `mir_dump`) + -W dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no) + -W dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no) + -W dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans. + -W emit-stack-sizes=val -- emit a section containing stack size metadata (default: no) + -W fewer-names=val -- reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) (default: no) + -W force-unstable-if-unmarked=val -- force all crates to be `rustc_private` unstable (default: no) + -W fuel=val -- set the optimization fuel quota for a crate + -W function-sections=val -- whether each function should go in its own section + -W future-incompat-test=val -- forces all lints to be future incompatible, used for internal testing (default: no) + -W gcc-ld=val -- implementation of ld used by cc + -W graphviz-dark-mode=val -- use dark-themed colors in graphviz output (default: no) + -W graphviz-font=val -- use the given `fontname` in graphviz output; can be overridden by setting environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`) + -W hir-stats=val -- print some statistics about AST and HIR (default: no) + -W human-readable-cgu-names=val -- generate human-readable, predictable names for codegen units (default: no) + -W identify-regions=val -- display unnamed regions as `'<id>`, using a non-ident unique id (default: no) + -W incremental-ignore-spans=val -- ignore spans during ICH computation -- used for testing (default: no) + -W incremental-info=val -- print high-level information about incremental reuse (or the lack thereof) (default: no) + -W incremental-relative-spans=val -- hash spans relative to their parent item for incr. comp. (default: no) + -W incremental-verify-ich=val -- verify incr. comp. hashes of green query instances (default: no) + -W inline-mir=val -- enable MIR inlining (default: no) + -W inline-mir-threshold=val -- a default MIR inlining threshold (default: 50) + -W inline-mir-hint-threshold=val -- inlining threshold for functions with inline hint (default: 100) + -W inline-in-all-cgus=val -- control whether `#[inline]` functions are in all CGUs + -W input-stats=val -- gather statistics about the input (default: no) + -W instrument-coverage=val -- instrument the generated code to support LLVM source-based code coverage reports (note, the compiler build config must include `profiler = true`); implies `-C symbol-mangling-version=v0`. Optional values are: + `=all` (implicit value) + `=except-unused-generics` + `=except-unused-functions` + `=off` (default) + -W instrument-mcount=val -- insert function instrument code for mcount-based tracing (default: no) + -W keep-hygiene-data=val -- keep hygiene data after analysis (default: no) + -W link-native-libraries=val -- link native libraries in the linker invocation (default: yes) + -W link-only=val -- link the `.rlink` file generated by `-Z no-link` (default: no) + -W llvm-plugins=val -- a list LLVM plugins to enable (space separated) + -W llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no) + -W location-detail=val -- comma separated list of location details to be tracked when using caller_location valid options are `file`, `line`, and `column` (default: all) + -W ls=val -- list the symbols defined by a library crate (default: no) + -W macro-backtrace=val -- show macro backtraces (default: no) + -W merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name + -W meta-stats=val -- gather metadata statistics (default: no) + -W mir-emit-retag=val -- emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 (default: no) + -W mir-enable-passes=val -- use like `-Zmir-enable-passes=+DestProp,-InstCombine`. Forces the specified passes to be enabled, overriding all other checks. Passes that are not specified are enabled or disabled by other flags as usual. + -W mir-opt-level=val -- MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds) + -W move-size-limit=val -- the size at which the `large_assignments` lint starts to be emitted + -W mutable-noalias=val -- emit noalias metadata for mutable references (default: yes) + -W new-llvm-pass-manager=val -- use new LLVM pass manager (default: no) + -W nll-facts=val -- dump facts from NLL analysis into side files (default: no) + -W nll-facts-dir=val -- the directory the NLL facts are dumped into (default: `nll-facts`) + -W no-analysis=val -- parse and expand the source, but run no analysis + -W no-codegen=val -- run all passes except codegen; no output + -W no-generate-arange-section=val -- omit DWARF address ranges that give faster lookups + -W no-interleave-lints=val -- execute lints separately; allows benchmarking individual lints + -W no-leak-check=val -- disable the 'leak check' for subtyping; unsound, but useful for tests + -W no-link=val -- compile without linking + -W no-parallel-llvm=val -- run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO) + -W no-unique-section-names=val -- do not use unique names for text and data sections when -Z function-sections is used + -W no-profiler-runtime=val -- prevent automatic injection of the profiler_builtins crate + -W normalize-docs=val -- normalize associated items in rustdoc when generating documentation + -W oom=val -- panic strategy for out-of-memory handling + -W osx-rpath-install-name=val -- pass `-install_name @rpath/...` to the macOS linker (default: no) + -W panic-abort-tests=val -- support compiling tests with panic=abort (default: no) + -W panic-in-drop=val -- panic strategy for panics in drops + -W parse-only=val -- parse only; do not compile, assemble, or link (default: no) + -W perf-stats=val -- print some performance-related statistics (default: no) + -W pick-stable-methods-before-any-unstable=val -- try to pick stable methods first before picking any unstable methods (default: yes) + -W plt=val -- whether to use the PLT when calling into shared libraries; + only has effect for PIC code on systems with ELF binaries + (default: PLT is disabled if full relro is enabled) + -W polonius=val -- enable polonius-based borrow-checker (default: no) + -W polymorphize=val -- perform polymorphization analysis + -W pre-link-arg=val -- a single extra argument to prepend the linker invocation (can be used several times) + -W pre-link-args=val -- extra arguments to prepend to the linker invocation (space separated) + -W precise-enum-drop-elaboration=val -- use a more precise version of drop elaboration for matches on enums (default: yes). This results in better codegen, but has caused miscompilations on some tier 2 platforms. See #77382 and #74551. + -W print-fuel=val -- make rustc print the total optimization fuel used by a crate + -W print-llvm-passes=val -- print the LLVM optimization passes being run (default: no) + -W print-mono-items=val -- print the result of the monomorphization collection pass + -W print-type-sizes=val -- print layout information for each type encountered (default: no) + -W proc-macro-backtrace=val -- show backtraces for panics during proc-macro execution (default: no) + -W profile=val -- insert profiling code (default: no) + -W profile-closures=val -- profile size of closures + -W profile-emit=val -- file path to emit profiling data at runtime when using 'profile' (default based on relative source path) + -W profiler-runtime=val -- name of the profiler runtime crate to automatically inject (default: `profiler_builtins`) + -W profile-sample-use=val -- use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO) + -W query-dep-graph=val -- enable queries of the dependency graph for regression testing (default: no) + -W randomize-layout=val -- randomize the layout of types (default: no) + -W layout-seed=val -- seed layout randomization + -W relax-elf-relocations=val -- whether ELF relocations can be relaxed + -W relro-level=val -- choose which RELRO level to use + -W remap-cwd-prefix=val -- remap paths under the current working directory to this path prefix + -W simulate-remapped-rust-src-base=val -- simulate the effect of remap-debuginfo = true at bootstrapping by remapping path to rust's source base directory. only meant for testing purposes + -W report-delayed-bugs=val -- immediately print bugs registered with `delay_span_bug` (default: no) + -W sanitizer=val -- use a sanitizer + -W sanitizer-memory-track-origins=val -- enable origins tracking in MemorySanitizer + -W sanitizer-recover=val -- enable recovery for selected sanitizers + -W saturating-float-casts=val -- make float->int casts UB-free: numbers outside the integer type's range are clipped to the max/min integer respectively, and NaN is mapped to 0 (default: yes) + -W save-analysis=val -- write syntax and type analysis (in JSON format) information, in addition to normal output (default: no) + -W self-profile=val -- run the self profiler and output the raw event data + -W self-profile-events=val -- specify the events recorded by the self profiler; + for example: `-Z self-profile-events=default,query-keys` + all options: none, all, default, generic-activity, query-provider, query-cache-hit + query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm, artifact-sizes + -W self-profile-counter=val -- counter used by the self profiler (default: `wall-time`), one of: + `wall-time` (monotonic clock, i.e. `std::time::Instant`) + `instructions:u` (retired instructions, userspace-only) + `instructions-minus-irqs:u` (subtracting hardware interrupt counts for extra accuracy) + -W share-generics=val -- make the current crate share its generic instantiations + -W show-span=val -- show spans for compiler debugging (expr|pat|ty) + -W span-debug=val -- forward proc_macro::Span's `Debug` impl to `Span` + -W span-free-formats=val -- exclude spans when debug-printing compiler state (default: no) + -W src-hash-algorithm=val -- hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`) + -W stack-protector=val -- control stack smash protection strategy (`rustc --print stack-protector-strategies` for details) + -W strict-init-checks=val -- control if mem::uninitialized and mem::zeroed panic on more UB + -W strip=val -- tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`) + -W split-dwarf-kind=val -- split dwarf variant (only if -Csplit-debuginfo is enabled and on relevant platform) + (default: `split`) -Available lint options: - -W <foo> Warn about <foo> - -A <foo> Allow <foo> - -D <foo> Deny <foo> - -F <foo> Forbid <foo> (deny <foo> and all attempts to override) - - -Lint checks provided by rustc: - - $NAMES $LEVELS $MEANINGS - -Lint groups provided by rustc: - - $NAMES $SUB_LINTS - -Lint checks provided by plugins loaded by this crate: - - $NAMES $LEVELS $MEANINGS - -Lint groups provided by plugins loaded by this crate: - - rustdoc::all $GROUPS - - + `split`: sections which do not require relocation are written into a DWARF object (`.dwo`) + file which is ignored by the linker + `single`: sections which do not require relocation are written into object file but ignored + by the linker + -W split-dwarf-inlining=val -- provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF + -W symbol-mangling-version=val -- which mangling version to use for symbol names ('legacy' (default) or 'v0') + -W teach=val -- show extended diagnostic help (default: no) + -W temps-dir=val -- the directory the intermediate files are written to + -W terminal-width=val -- set the current terminal width + -W translate-lang=val -- language identifier for diagnostic output + -W translate-additional-ftl=val -- additional fluent translation to preferentially use (for testing translation) + -W translate-directionality-markers=val -- emit directionality isolation markers in translated diagnostics + -W tune-cpu=val -- select processor to schedule for (`rustc --print target-cpus` for details) + -W thinlto=val -- enable ThinLTO when possible + -W thir-unsafeck=val -- use the THIR unsafety checker (default: no) + -W threads=val -- use a thread pool with N threads + -W time=val -- measure time of rustc processes (default: no) + -W time-llvm-passes=val -- measure time of each LLVM pass (default: no) + -W time-passes=val -- measure time of each rustc pass (default: no) + -W tls-model=val -- choose the TLS model to use (`rustc --print tls-models` for details) + -W trace-macros=val -- for every macro invocation, print its name and arguments (default: no) + -W translate-remapped-path-to-local-path=val -- translate remapped paths into local paths when possible (default: yes) + -W trap-unreachable=val -- generate trap instructions for unreachable intrinsics (default: use target setting, usually yes) + -W treat-err-as-bug=val -- treat error number `val` that occurs as bug + -W trim-diagnostic-paths=val -- in diagnostics, use heuristics to shorten paths referring to items + -W ui-testing=val -- emit compiler diagnostics in a form suitable for UI testing (default: no) + -W uninit-const-chunk-threshold=val -- allow generating const initializers with mixed init/uninit chunks, and set the maximum number of chunks for which this is allowed (default: 16) + -W unleash-the-miri-inside-of-you=val -- take the brakes off const evaluation. NOTE: this is unsound (default: no) + -W unpretty=val -- present the input source, unstable (and less-pretty) variants; + `normal`, `identified`, + `expanded`, `expanded,identified`, + `expanded,hygiene` (with internal representations), + `ast-tree` (raw AST before expansion), + `ast-tree,expanded` (raw AST after expansion), + `hir` (the HIR), `hir,identified`, + `hir,typed` (HIR with types for each node), + `hir-tree` (dump the raw HIR), + `mir` (the MIR), or `mir-cfg` (graphviz formatted MIR) + -W unsound-mir-opts=val -- enable unsound and buggy MIR optimizations (default: no) + -W unstable-options=val -- adds unstable command line options to rustc interface (default: no) + -W use-ctors-section=val -- use legacy .ctors section for initializers rather than .init_array + -W validate-mir=val -- validate MIR after each transformation + -W verbose=val -- in general, enable more debug printouts (default: no) + -W verify-llvm-ir=val -- verify LLVM IR (default: no) + -W virtual-function-elimination=val -- enables dead virtual function elimination optimization. Requires `-Clto[=[fat,yes]]` + -W wasi-exec-model=val -- whether to build a wasi command or reactor diff --git a/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr b/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr index ea475ffc554..ad21b38d07e 100644 --- a/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr +++ b/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr @@ -4,7 +4,7 @@ error[E0201]: duplicate definitions with name `bar`: LL | const bar: bool = true; | ----------------------- previous definition of `bar` here LL | fn bar() {} - | ^^^^^^^^^^^ duplicate definition + | ^^^^^^^^ duplicate definition error: aborting due to previous error diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr index 9ae25a8c222..5487af1a835 100644 --- a/src/test/ui/associated-item/issue-48027.stderr +++ b/src/test/ui/associated-item/issue-48027.stderr @@ -1,15 +1,3 @@ -error[E0283]: type annotations needed - --> $DIR/issue-48027.rs:3:32 - | -LL | fn return_n(&self) -> [u8; Bar::X]; - | ^^^^^^ - | | - | cannot infer type - | help: use the fully qualified path to an implementation: `<Type as Bar>::X` - | - = note: cannot satisfy `_: Bar` - = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` - error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/issue-48027.rs:6:6 | @@ -25,6 +13,18 @@ LL | const X: usize; | ^ ...because it contains this associated `const` = help: consider moving `X` to another trait +error[E0283]: type annotations needed + --> $DIR/issue-48027.rs:3:32 + | +LL | fn return_n(&self) -> [u8; Bar::X]; + | ^^^^^^ + | | + | cannot infer type + | help: use the fully qualified path to an implementation: `<Type as Bar>::X` + | + = note: cannot satisfy `_: Bar` + = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` + error: aborting due to 2 previous errors Some errors have detailed explanations: E0038, E0283. diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr index da79c7ac77f..bd3ee2abd2c 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr @@ -1,3 +1,9 @@ +error[E0277]: the trait bound `(T, U): Get` is not satisfied + --> $DIR/associated-types-no-suitable-supertrait.rs:22:40 + | +LL | fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {} + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)` + error[E0277]: the trait bound `Self: Get` is not satisfied --> $DIR/associated-types-no-suitable-supertrait.rs:17:40 | @@ -9,12 +15,6 @@ help: consider further restricting `Self` LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Get {} | +++++++++++++++ -error[E0277]: the trait bound `(T, U): Get` is not satisfied - --> $DIR/associated-types-no-suitable-supertrait.rs:22:40 - | -LL | fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)` - error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-2.rs b/src/test/ui/associated-types/hr-associated-type-bound-2.rs index 2eb956c8dbb..a89f61a81a5 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-2.rs +++ b/src/test/ui/associated-types/hr-associated-type-bound-2.rs @@ -12,7 +12,7 @@ impl X<'_> for u32 //~ overflow evaluating the requirement `for<'b> u32: X<'b>` where for<'b> <Self as X<'b>>::U: Clone, { - type U = str; //~ overflow evaluating the requirement `for<'b> u32: X<'b>` + type U = str; } fn main() { diff --git a/src/test/ui/associated-types/hr-associated-type-bound-2.stderr b/src/test/ui/associated-types/hr-associated-type-bound-2.stderr index fe9b4d630b9..1d3b7097da6 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-2.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-2.stderr @@ -18,21 +18,6 @@ LL | impl X<'_> for u32 = note: 128 redundant requirements hidden = note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32` -error[E0275]: overflow evaluating the requirement `for<'b> u32: X<'b>` - --> $DIR/hr-associated-type-bound-2.rs:15:5 - | -LL | type U = str; - | ^^^^^^^^^^^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`hr_associated_type_bound_2`) -note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32` - --> $DIR/hr-associated-type-bound-2.rs:11:6 - | -LL | impl X<'_> for u32 - | ^^^^^ ^^^ - = note: 128 redundant requirements hidden - = note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32` - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr index 5809c407a5f..52294f8c94a 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr @@ -15,10 +15,10 @@ LL | for<'b> <T as Z<'b, u16>>::W: Clone, | ^^^^^ required by this bound in `Z` error[E0277]: the trait bound `str: Clone` is not satisfied - --> $DIR/hr-associated-type-bound-param-2.rs:3:8 + --> $DIR/hr-associated-type-bound-param-2.rs:15:14 | -LL | T: Z<'a, u16>, - | ^^^^^^^^^^ the trait `Clone` is not implemented for `str` +LL | type W = str; + | ^^^ the trait `Clone` is not implemented for `str` | = help: the trait `Clone` is implemented for `String` note: required by a bound in `Z` @@ -31,10 +31,10 @@ LL | for<'b> <T as Z<'b, u16>>::W: Clone, | ^^^^^ required by this bound in `Z` error[E0277]: the trait bound `str: Clone` is not satisfied - --> $DIR/hr-associated-type-bound-param-2.rs:15:14 + --> $DIR/hr-associated-type-bound-param-2.rs:3:8 | -LL | type W = str; - | ^^^ the trait `Clone` is not implemented for `str` +LL | T: Z<'a, u16>, + | ^^^^^^^^^^ the trait `Clone` is not implemented for `str` | = help: the trait `Clone` is implemented for `String` note: required by a bound in `Z` diff --git a/src/test/ui/associated-types/impl-wf-cycle-1.rs b/src/test/ui/associated-types/impl-wf-cycle-1.rs index ba074210a2b..365eddaed13 100644 --- a/src/test/ui/associated-types/impl-wf-cycle-1.rs +++ b/src/test/ui/associated-types/impl-wf-cycle-1.rs @@ -13,16 +13,14 @@ trait Grault { } impl<T: Grault> Grault for (T,) +//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _` where Self::A: Baz, Self::B: Fiz, { type A = (); - //~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _` type B = bool; - //~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _` } -//~^^^^^^^^^^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _` fn main() { let x: <(_,) as Grault>::A = (); diff --git a/src/test/ui/associated-types/impl-wf-cycle-1.stderr b/src/test/ui/associated-types/impl-wf-cycle-1.stderr index 73167d08311..6f60128b8ef 100644 --- a/src/test/ui/associated-types/impl-wf-cycle-1.stderr +++ b/src/test/ui/associated-types/impl-wf-cycle-1.stderr @@ -2,11 +2,11 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` --> $DIR/impl-wf-cycle-1.rs:15:1 | LL | / impl<T: Grault> Grault for (T,) +LL | | LL | | where LL | | Self::A: Baz, -LL | | Self::B: Fiz, ... | -LL | | +LL | | type B = bool; LL | | } | |_^ | @@ -18,34 +18,6 @@ LL | impl<T: Grault> Grault for (T,) = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `Grault` for `(T,)` -error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` - --> $DIR/impl-wf-cycle-1.rs:20:5 - | -LL | type A = (); - | ^^^^^^^^^^^^ - | -note: required because of the requirements on the impl of `Grault` for `(T,)` - --> $DIR/impl-wf-cycle-1.rs:15:17 - | -LL | impl<T: Grault> Grault for (T,) - | ^^^^^^ ^^^^ - = note: 1 redundant requirement hidden - = note: required because of the requirements on the impl of `Grault` for `(T,)` - -error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` - --> $DIR/impl-wf-cycle-1.rs:22:5 - | -LL | type B = bool; - | ^^^^^^^^^^^^^^ - | -note: required because of the requirements on the impl of `Grault` for `(T,)` - --> $DIR/impl-wf-cycle-1.rs:15:17 - | -LL | impl<T: Grault> Grault for (T,) - | ^^^^^^ ^^^^ - = note: 1 redundant requirement hidden - = note: required because of the requirements on the impl of `Grault` for `(T,)` - -error: aborting due to 3 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/associated-types/impl-wf-cycle-2.rs b/src/test/ui/associated-types/impl-wf-cycle-2.rs index 6fccc54f229..f2f3072e344 100644 --- a/src/test/ui/associated-types/impl-wf-cycle-2.rs +++ b/src/test/ui/associated-types/impl-wf-cycle-2.rs @@ -5,12 +5,11 @@ trait Grault { } impl<T: Grault> Grault for (T,) +//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _` where Self::A: Copy, { type A = (); - //~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _` } -//~^^^^^^^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _` fn main() {} diff --git a/src/test/ui/associated-types/impl-wf-cycle-2.stderr b/src/test/ui/associated-types/impl-wf-cycle-2.stderr index a17e63f28fe..ba14ffefae5 100644 --- a/src/test/ui/associated-types/impl-wf-cycle-2.stderr +++ b/src/test/ui/associated-types/impl-wf-cycle-2.stderr @@ -2,11 +2,11 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` --> $DIR/impl-wf-cycle-2.rs:7:1 | LL | / impl<T: Grault> Grault for (T,) +LL | | LL | | where LL | | Self::A: Copy, LL | | { LL | | type A = (); -LL | | LL | | } | |_^ | @@ -16,18 +16,6 @@ note: required because of the requirements on the impl of `Grault` for `(T,)` LL | impl<T: Grault> Grault for (T,) | ^^^^^^ ^^^^ -error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` - --> $DIR/impl-wf-cycle-2.rs:11:5 - | -LL | type A = (); - | ^^^^^^^^^^^^ - | -note: required because of the requirements on the impl of `Grault` for `(T,)` - --> $DIR/impl-wf-cycle-2.rs:7:17 - | -LL | impl<T: Grault> Grault for (T,) - | ^^^^^^ ^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/associated-types/issue-59324.stderr b/src/test/ui/associated-types/issue-59324.stderr index 45d2dfb5375..5cd781d9a0c 100644 --- a/src/test/ui/associated-types/issue-59324.stderr +++ b/src/test/ui/associated-types/issue-59324.stderr @@ -46,6 +46,12 @@ help: consider further restricting this bound LL | pub trait ThriftService<Bug: NotFoo + Foo>: | +++++ +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/issue-59324.rs:23:29 + | +LL | fn with_factory<H>(factory: dyn ThriftService<()>) {} + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` + error[E0277]: the trait bound `Bug: Foo` is not satisfied --> $DIR/issue-59324.rs:19:10 | @@ -57,12 +63,6 @@ help: consider further restricting this bound LL | pub trait ThriftService<Bug: NotFoo + Foo>: | +++++ -error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/issue-59324.rs:23:29 - | -LL | fn with_factory<H>(factory: dyn ThriftService<()>) {} - | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` - error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/chalkify/bugs/async.rs b/src/test/ui/chalkify/bugs/async.rs index 58fc93064ed..ae5224dbd6f 100644 --- a/src/test/ui/chalkify/bugs/async.rs +++ b/src/test/ui/chalkify/bugs/async.rs @@ -1,5 +1,5 @@ // check-fail -// known-bug +// known-bug: unknown // compile-flags: -Z chalk --edition=2021 fn main() -> () {} diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr index 91289148079..c364c707ff9 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr @@ -1,3 +1,15 @@ +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 + | +LL | impl !Marker1 for dyn Object + Marker2 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` + +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1 + | +LL | impl !Marker2 for dyn Object + Marker2 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` + error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:23:1 | @@ -21,18 +33,6 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i LL | impl !Send for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type -error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 - | -LL | impl !Marker1 for dyn Object + Marker2 { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` - -error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1 - | -LL | impl !Marker2 for dyn Object + Marker2 { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` - error: aborting due to 5 previous errors Some errors have detailed explanations: E0117, E0321, E0371. diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr index 056198374a4..b80429794f9 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr @@ -1,3 +1,15 @@ +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1 + | +LL | impl Marker1 for dyn Object + Marker2 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` + +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1 + | +LL | impl Marker2 for dyn Object + Marker2 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` + error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:23:1 | @@ -21,18 +33,6 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i LL | unsafe impl Send for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type -error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1 - | -LL | impl Marker1 for dyn Object + Marker2 { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` - -error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1 - | -LL | impl Marker2 for dyn Object + Marker2 { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` - error: aborting due to 5 previous errors Some errors have detailed explanations: E0117, E0321, E0371. diff --git a/src/test/ui/coherence/coherence-impls-copy.stderr b/src/test/ui/coherence/coherence-impls-copy.stderr index b3ca354c633..86356af2564 100644 --- a/src/test/ui/coherence/coherence-impls-copy.stderr +++ b/src/test/ui/coherence/coherence-impls-copy.stderr @@ -9,49 +9,49 @@ LL | impl Copy for i32 {} | = note: define and implement a trait or new type instead +error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&NotSync` + --> $DIR/coherence-impls-copy.rs:28:1 + | +LL | impl Copy for &'static NotSync {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl<T> Copy for &T + where T: ?Sized; + error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-copy.rs:25:1 + --> $DIR/coherence-impls-copy.rs:33:1 | -LL | impl Copy for (MyType, MyType) {} - | ^^^^^^^^^^^^^^---------------- +LL | impl Copy for &'static [NotSync] {} + | ^^^^^^^^^^^^^^------------------ | | | - | | this is not defined in the current crate because tuples are always foreign + | | this is not defined in the current crate because slices are always foreign | impl doesn't use only types from inside the current crate | = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-copy.rs:30:1 + --> $DIR/coherence-impls-copy.rs:25:1 | -LL | impl Copy for [MyType] {} - | ^^^^^^^^^^^^^^-------- +LL | impl Copy for (MyType, MyType) {} + | ^^^^^^^^^^^^^^---------------- | | | - | | this is not defined in the current crate because slices are always foreign + | | this is not defined in the current crate because tuples are always foreign | impl doesn't use only types from inside the current crate | = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-copy.rs:33:1 + --> $DIR/coherence-impls-copy.rs:30:1 | -LL | impl Copy for &'static [NotSync] {} - | ^^^^^^^^^^^^^^------------------ +LL | impl Copy for [MyType] {} + | ^^^^^^^^^^^^^^-------- | | | | | this is not defined in the current crate because slices are always foreign | impl doesn't use only types from inside the current crate | = note: define and implement a trait or new type instead -error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&NotSync` - --> $DIR/coherence-impls-copy.rs:28:1 - | -LL | impl Copy for &'static NotSync {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: conflicting implementation in crate `core`: - - impl<T> Copy for &T - where T: ?Sized; - error[E0206]: the trait `Copy` may not be implemented for this type --> $DIR/coherence-impls-copy.rs:21:15 | diff --git a/src/test/ui/coherence/coherence-impls-send.stderr b/src/test/ui/coherence/coherence-impls-send.stderr index dd1fd1b0dce..e1071846e14 100644 --- a/src/test/ui/coherence/coherence-impls-send.stderr +++ b/src/test/ui/coherence/coherence-impls-send.stderr @@ -1,4 +1,15 @@ error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-send.rs:25:1 + | +LL | unsafe impl Send for &'static [NotSync] {} + | ^^^^^^^^^^^^^^^^^^^^^------------------ + | | | + | | this is not defined in the current crate because slices are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/coherence-impls-send.rs:16:1 | LL | unsafe impl Send for (MyType, MyType) {} @@ -26,17 +37,6 @@ LL | unsafe impl Send for [MyType] {} | = note: define and implement a trait or new type instead -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-send.rs:25:1 - | -LL | unsafe impl Send for &'static [NotSync] {} - | ^^^^^^^^^^^^^^^^^^^^^------------------ - | | | - | | this is not defined in the current crate because slices are always foreign - | impl doesn't use only types from inside the current crate - | - = note: define and implement a trait or new type instead - error: aborting due to 4 previous errors Some errors have detailed explanations: E0117, E0321. diff --git a/src/test/ui/coherence/coherence-impls-sized.stderr b/src/test/ui/coherence/coherence-impls-sized.stderr index e1e4acd4cd8..17a7544521d 100644 --- a/src/test/ui/coherence/coherence-impls-sized.stderr +++ b/src/test/ui/coherence/coherence-impls-sized.stderr @@ -1,36 +1,3 @@ -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-sized.rs:20:1 - | -LL | impl Sized for (MyType, MyType) {} - | ^^^^^^^^^^^^^^^---------------- - | | | - | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use only types from inside the current crate - | - = note: define and implement a trait or new type instead - -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-sized.rs:27:1 - | -LL | impl Sized for [MyType] {} - | ^^^^^^^^^^^^^^^-------- - | | | - | | this is not defined in the current crate because slices are always foreign - | impl doesn't use only types from inside the current crate - | - = note: define and implement a trait or new type instead - -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-sized.rs:31:1 - | -LL | impl Sized for &'static [NotSync] {} - | ^^^^^^^^^^^^^^^------------------ - | | | - | | this is not defined in the current crate because slices are always foreign - | impl doesn't use only types from inside the current crate - | - = note: define and implement a trait or new type instead - error[E0322]: explicit impls for the `Sized` trait are not permitted --> $DIR/coherence-impls-sized.rs:14:1 | @@ -49,6 +16,17 @@ error[E0322]: explicit impls for the `Sized` trait are not permitted LL | impl Sized for (MyType, MyType) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-sized.rs:20:1 + | +LL | impl Sized for (MyType, MyType) {} + | ^^^^^^^^^^^^^^^---------------- + | | | + | | this is not defined in the current crate because tuples are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + error[E0322]: explicit impls for the `Sized` trait are not permitted --> $DIR/coherence-impls-sized.rs:24:1 | @@ -61,12 +39,34 @@ error[E0322]: explicit impls for the `Sized` trait are not permitted LL | impl Sized for [MyType] {} | ^^^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-sized.rs:27:1 + | +LL | impl Sized for [MyType] {} + | ^^^^^^^^^^^^^^^-------- + | | | + | | this is not defined in the current crate because slices are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + error[E0322]: explicit impls for the `Sized` trait are not permitted --> $DIR/coherence-impls-sized.rs:31:1 | LL | impl Sized for &'static [NotSync] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-sized.rs:31:1 + | +LL | impl Sized for &'static [NotSync] {} + | ^^^^^^^^^^^^^^^------------------ + | | | + | | this is not defined in the current crate because slices are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + error: aborting due to 9 previous errors Some errors have detailed explanations: E0117, E0322. diff --git a/src/test/ui/coherence/coherence-with-closure.stderr b/src/test/ui/coherence/coherence-with-closure.stderr index 20b986cee69..d2ca63fa146 100644 --- a/src/test/ui/coherence/coherence-with-closure.stderr +++ b/src/test/ui/coherence/coherence-with-closure.stderr @@ -1,3 +1,12 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>` + --> $DIR/coherence-with-closure.rs:12:1 + | +LL | impl Trait for Wrapper<OpaqueClosure> {} + | ------------------------------------- first implementation here +LL | +LL | impl<T: Sync> Trait for Wrapper<T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueClosure>` + error: cannot implement trait on type alias impl trait --> $DIR/coherence-with-closure.rs:10:24 | @@ -10,15 +19,6 @@ note: type alias impl trait defined here LL | type OpaqueClosure = impl Sized; | ^^^^^^^^^^ -error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>` - --> $DIR/coherence-with-closure.rs:12:1 - | -LL | impl Trait for Wrapper<OpaqueClosure> {} - | ------------------------------------- first implementation here -LL | -LL | impl<T: Sync> Trait for Wrapper<T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueClosure>` - error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence/coherence-with-generator.stderr b/src/test/ui/coherence/coherence-with-generator.stderr index 249ad3cb9ec..804bc1c3a6d 100644 --- a/src/test/ui/coherence/coherence-with-generator.stderr +++ b/src/test/ui/coherence/coherence-with-generator.stderr @@ -1,3 +1,12 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>` + --> $DIR/coherence-with-generator.rs:16:1 + | +LL | impl Trait for Wrapper<OpaqueGenerator> {} + | --------------------------------------- first implementation here +LL | +LL | impl<T: Sync> Trait for Wrapper<T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueGenerator>` + error: cannot implement trait on type alias impl trait --> $DIR/coherence-with-generator.rs:14:24 | @@ -10,15 +19,6 @@ note: type alias impl trait defined here LL | type OpaqueGenerator = impl Sized; | ^^^^^^^^^^ -error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>` - --> $DIR/coherence-with-generator.rs:16:1 - | -LL | impl Trait for Wrapper<OpaqueGenerator> {} - | --------------------------------------- first implementation here -LL | -LL | impl<T: Sync> Trait for Wrapper<T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueGenerator>` - error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr b/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr index 48d85e7ff64..4bba42c7782 100644 --- a/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr +++ b/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr @@ -47,15 +47,6 @@ LL | impl<const N: &u8> A<N> { = help: more complex types are supported with `#![feature(adt_const_params)]` error: `&'static u8` is forbidden as the type of a const generic parameter - --> $DIR/const-param-elided-lifetime.rs:17:21 - | -LL | fn foo<const M: &u8>(&self) {} - | ^^^ - | - = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` - -error: `&'static u8` is forbidden as the type of a const generic parameter --> $DIR/const-param-elided-lifetime.rs:22:15 | LL | impl<const N: &u8> B for A<N> {} @@ -73,6 +64,15 @@ LL | fn bar<const N: &u8>() {} = note: the only supported types are integers, `bool` and `char` = help: more complex types are supported with `#![feature(adt_const_params)]` +error: `&'static u8` is forbidden as the type of a const generic parameter + --> $DIR/const-param-elided-lifetime.rs:17:21 + | +LL | fn foo<const M: &u8>(&self) {} + | ^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0637`. diff --git a/src/test/ui/error-codes/E0201.stderr b/src/test/ui/error-codes/E0201.stderr index 89cfd402423..af029603fa1 100644 --- a/src/test/ui/error-codes/E0201.stderr +++ b/src/test/ui/error-codes/E0201.stderr @@ -2,17 +2,17 @@ error[E0201]: duplicate definitions with name `bar`: --> $DIR/E0201.rs:5:5 | LL | fn bar(&self) -> bool { self.0 > 5 } - | ------------------------------------ previous definition of `bar` here + | --------------------- previous definition of `bar` here LL | fn bar() {} - | ^^^^^^^^^^^ duplicate definition + | ^^^^^^^^ duplicate definition error[E0201]: duplicate definitions with name `baz`: --> $DIR/E0201.rs:17:5 | LL | fn baz(&self) -> bool { true } - | ------------------------------ previous definition of `baz` here + | --------------------- previous definition of `baz` here LL | fn baz(&self) -> bool { self.0 > 5 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition + | ^^^^^^^^^^^^^^^^^^^^^ duplicate definition error[E0201]: duplicate definitions with name `Quux`: --> $DIR/E0201.rs:18:5 diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr index a06c4b2b483..a1c69a5afb6 100644 --- a/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr +++ b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr @@ -1,13 +1,3 @@ -error[E0658]: `Ptr<Self>` cannot be used as the type of `self` without the `arbitrary_self_types` feature - --> $DIR/feature-gate-arbitrary-self-types.rs:16:18 - | -LL | fn foo(self: Ptr<Self>); - | ^^^^^^^^^ - | - = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information - = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) - error[E0658]: `Ptr<Bar>` cannot be used as the type of `self` without the `arbitrary_self_types` feature --> $DIR/feature-gate-arbitrary-self-types.rs:22:18 | @@ -28,6 +18,16 @@ LL | fn bar(self: Box<Ptr<Self>>) {} = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) +error[E0658]: `Ptr<Self>` cannot be used as the type of `self` without the `arbitrary_self_types` feature + --> $DIR/feature-gate-arbitrary-self-types.rs:16:18 + | +LL | fn foo(self: Ptr<Self>); + | ^^^^^^^^^ + | + = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information + = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr index f9c53a66c4b..a9f611b8745 100644 --- a/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr +++ b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr @@ -8,20 +8,20 @@ LL | fn foo(self: *const Self) {} = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) -error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature - --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:9:18 +error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types` feature + --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18 | -LL | fn bar(self: *const Self); +LL | fn bar(self: *const Self) {} | ^^^^^^^^^^^ | = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) -error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types` feature - --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18 +error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature + --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:9:18 | -LL | fn bar(self: *const Self) {} +LL | fn bar(self: *const Self); | ^^^^^^^^^^^ | = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.rs b/src/test/ui/generic-associated-types/bugs/issue-80626.rs index a637da6cf6f..14f27aff1cc 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-80626.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-80626.rs @@ -1,5 +1,5 @@ // check-fail -// known-bug +// known-bug: #80626 // This should pass, but it requires `Sized` to be coinductive. diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.stderr b/src/test/ui/generic-associated-types/bugs/issue-80626.stderr index 8b0cc78e999..487b83dfa3f 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-80626.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-80626.stderr @@ -4,16 +4,11 @@ error[E0275]: overflow evaluating the requirement `LinkedList<A>: Sized` LL | Next(A::Allocated<Self>) | ^^^^^^^^^^^^^^^^^^ | - = note: no field of an enum variant may have a dynamically sized type - = help: change the field's type to have a statically known size -help: borrowed types always have a statically known size +note: required by a bound in `Allocator::Allocated` + --> $DIR/issue-80626.rs:9:20 | -LL | Next(&A::Allocated<Self>) - | + -help: the `Box` type always has a statically known size and allocates its contents in the heap - | -LL | Next(Box<A::Allocated<Self>>) - | ++++ + +LL | type Allocated<T>; + | ^ required by this bound in `Allocator::Allocated` error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.rs b/src/test/ui/generic-associated-types/bugs/issue-86218.rs index 68cd0fd7efc..fb62c10a9e3 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-86218.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-86218.rs @@ -1,5 +1,5 @@ // check-fail -// known-bug +// known-bug: #86218 // This should pass, but seems to run into a TAIT issue. diff --git a/src/test/ui/generic-associated-types/bugs/issue-87735.rs b/src/test/ui/generic-associated-types/bugs/issue-87735.rs index 53e3ad7fe69..0844d84c34f 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87735.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-87735.rs @@ -1,5 +1,5 @@ // check-fail -// known-bug +// known-bug: #87735, #88526 // This should pass, but we need an extension of implied bounds (probably). diff --git a/src/test/ui/generic-associated-types/bugs/issue-87748.rs b/src/test/ui/generic-associated-types/bugs/issue-87748.rs index 6e7cd45bdb1..a3d00ee03b1 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87748.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-87748.rs @@ -1,5 +1,5 @@ // check-fail -// known-bug +// known-bug: #87748 // This should pass, but unnormalized input args aren't treated as implied. diff --git a/src/test/ui/generic-associated-types/bugs/issue-87755.rs b/src/test/ui/generic-associated-types/bugs/issue-87755.rs index 31cea12a3e2..efa487d624f 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87755.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-87755.rs @@ -1,5 +1,5 @@ // check-fail -// known-bug +// known-bug: #87755 // This should pass. diff --git a/src/test/ui/generic-associated-types/bugs/issue-87803.rs b/src/test/ui/generic-associated-types/bugs/issue-87803.rs index 57a4b028d93..a8a111c99ef 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87803.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-87803.rs @@ -1,5 +1,5 @@ // check-fail -// known-bug +// known-bug: #87803 // This should pass, but using a type alias vs a reference directly // changes late-bound -> early-bound. diff --git a/src/test/ui/generic-associated-types/bugs/issue-88382.rs b/src/test/ui/generic-associated-types/bugs/issue-88382.rs index c9f34240527..5493b9b9391 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88382.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-88382.rs @@ -1,5 +1,5 @@ // check-fail -// known-bug +// known-bug: #88382 // This should pass, but has a missed normalization due to HRTB. diff --git a/src/test/ui/generic-associated-types/bugs/issue-88460.rs b/src/test/ui/generic-associated-types/bugs/issue-88460.rs index b31d012d2fc..f1c3b226915 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88460.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-88460.rs @@ -1,5 +1,5 @@ // check-fail -// known-bug +// known-bug: #88460 // This should pass, but has a missed normalization due to HRTB. diff --git a/src/test/ui/generic-associated-types/bugs/issue-88526.rs b/src/test/ui/generic-associated-types/bugs/issue-88526.rs index c72a450b926..15363ad04bf 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88526.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-88526.rs @@ -1,5 +1,5 @@ // check-fail -// known-bug +// known-bug: #88526 // This should pass, but requires more logic. diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.rs b/src/test/ui/generic-associated-types/bugs/issue-89008.rs index 1581b7105a8..79c28b0d221 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-89008.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-89008.rs @@ -1,6 +1,6 @@ // check-fail // edition:2021 -// known-bug +// known-bug: #88908 // This should pass, but seems to run into a TAIT bug. diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr index 7f45fb83cef..a6858154dfb 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr @@ -19,44 +19,44 @@ LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext` error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied - --> $DIR/issue-89118.rs:22:20 + --> $DIR/issue-89118.rs:29:9 | -LL | type Handler = Ctx<C::Dispatcher>; - | ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` +LL | impl<C> EthernetWorker<C> {} + | ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` | note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>` --> $DIR/issue-89118.rs:5:23 | LL | impl<B: BufferMut, C> BufferUdpStateContext<B> for C {} | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -note: required by a bound in `StackContext` - --> $DIR/issue-89118.rs:9:14 +note: required by a bound in `EthernetWorker` + --> $DIR/issue-89118.rs:28:14 | -LL | trait StackContext - | ------------ required by a bound in this +LL | struct EthernetWorker<C>(C) + | -------------- required by a bound in this LL | where -LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext` +LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EthernetWorker` error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied - --> $DIR/issue-89118.rs:29:9 + --> $DIR/issue-89118.rs:22:20 | -LL | impl<C> EthernetWorker<C> {} - | ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` +LL | type Handler = Ctx<C::Dispatcher>; + | ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` | note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>` --> $DIR/issue-89118.rs:5:23 | LL | impl<B: BufferMut, C> BufferUdpStateContext<B> for C {} | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -note: required by a bound in `EthernetWorker` - --> $DIR/issue-89118.rs:28:14 +note: required by a bound in `StackContext` + --> $DIR/issue-89118.rs:9:14 | -LL | struct EthernetWorker<C>(C) - | -------------- required by a bound in this +LL | trait StackContext + | ------------ required by a bound in this LL | where -LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EthernetWorker` +LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext` error: aborting due to 3 previous errors diff --git a/src/test/ui/hrtb/issue-95034.rs b/src/test/ui/hrtb/issue-95034.rs index aee6fe61ba8..d8edbe7e56b 100644 --- a/src/test/ui/hrtb/issue-95034.rs +++ b/src/test/ui/hrtb/issue-95034.rs @@ -1,4 +1,4 @@ -// known-bug +// known-bug: #95034 // failure-status: 101 // compile-flags: --edition=2021 --crate-type=lib // rustc-env:RUST_BACKTRACE=0 diff --git a/src/test/ui/impl-duplicate-methods.stderr b/src/test/ui/impl-duplicate-methods.stderr index b6dc4882fc8..c19702a5bf0 100644 --- a/src/test/ui/impl-duplicate-methods.stderr +++ b/src/test/ui/impl-duplicate-methods.stderr @@ -2,9 +2,9 @@ error[E0201]: duplicate definitions with name `orange`: --> $DIR/impl-duplicate-methods.rs:5:5 | LL | fn orange(&self) {} - | ------------------- previous definition of `orange` here + | ---------------- previous definition of `orange` here LL | fn orange(&self) {} - | ^^^^^^^^^^^^^^^^^^^ duplicate definition + | ^^^^^^^^^^^^^^^^ duplicate definition error: aborting due to previous error diff --git a/src/test/ui/impl-trait/auto-trait.stderr b/src/test/ui/impl-trait/auto-trait.stderr index 3b360f492b7..5e10272b0db 100644 --- a/src/test/ui/impl-trait/auto-trait.stderr +++ b/src/test/ui/impl-trait/auto-trait.stderr @@ -1,3 +1,12 @@ +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>` + --> $DIR/auto-trait.rs:21:1 + | +LL | impl<T: Send> AnotherTrait for T {} + | -------------------------------- first implementation here +... +LL | impl AnotherTrait for D<OpaqueType> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>` + error: cannot implement trait on type alias impl trait --> $DIR/auto-trait.rs:21:25 | @@ -10,15 +19,6 @@ note: type alias impl trait defined here LL | type OpaqueType = impl OpaqueTrait; | ^^^^^^^^^^^^^^^^ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>` - --> $DIR/auto-trait.rs:21:1 - | -LL | impl<T: Send> AnotherTrait for T {} - | -------------------------------- first implementation here -... -LL | impl AnotherTrait for D<OpaqueType> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>` - error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/impl-trait/negative-reasoning.stderr b/src/test/ui/impl-trait/negative-reasoning.stderr index 98f9fbd8fef..479b451855d 100644 --- a/src/test/ui/impl-trait/negative-reasoning.stderr +++ b/src/test/ui/impl-trait/negative-reasoning.stderr @@ -1,3 +1,14 @@ +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>` + --> $DIR/negative-reasoning.rs:19:1 + | +LL | impl<T: std::fmt::Debug> AnotherTrait for T {} + | ------------------------------------------- first implementation here +... +LL | impl AnotherTrait for D<OpaqueType> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>` + | + = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions + error: cannot implement trait on type alias impl trait --> $DIR/negative-reasoning.rs:19:25 | @@ -10,17 +21,6 @@ note: type alias impl trait defined here LL | type OpaqueType = impl OpaqueTrait; | ^^^^^^^^^^^^^^^^ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>` - --> $DIR/negative-reasoning.rs:19:1 - | -LL | impl<T: std::fmt::Debug> AnotherTrait for T {} - | ------------------------------------------- first implementation here -... -LL | impl AnotherTrait for D<OpaqueType> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>` - | - = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions - error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/impl-trait/nested-return-type2.rs b/src/test/ui/impl-trait/nested-return-type2.rs index 39928d543e1..279641a46c3 100644 --- a/src/test/ui/impl-trait/nested-return-type2.rs +++ b/src/test/ui/impl-trait/nested-return-type2.rs @@ -1,5 +1,3 @@ -// check-pass - trait Duh {} impl Duh for i32 {} @@ -20,11 +18,9 @@ impl<R: Duh, F: FnMut() -> R> Trait for F { // the hidden type. We already have obligations registered on the inference // var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque // type does not implement `Duh`, even if its hidden type does. -// Lazy TAIT would error out, but we inserted a hack to make it work again, -// keeping backwards compatibility. fn foo() -> impl Trait<Assoc = impl Send> { + //~^ ERROR `impl Send: Duh` is not satisfied || 42 } -fn main() { -} +fn main() {} diff --git a/src/test/ui/impl-trait/nested-return-type2.stderr b/src/test/ui/impl-trait/nested-return-type2.stderr new file mode 100644 index 00000000000..f996e99de07 --- /dev/null +++ b/src/test/ui/impl-trait/nested-return-type2.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `impl Send: Duh` is not satisfied + --> $DIR/nested-return-type2.rs:21:13 + | +LL | fn foo() -> impl Trait<Assoc = impl Send> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Duh` is not implemented for `impl Send` + | + = help: the trait `Duh` is implemented for `i32` +note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2.rs:23:5: 23:10]` + --> $DIR/nested-return-type2.rs:12:31 + | +LL | impl<R: Duh, F: FnMut() -> R> Trait for F { + | ^^^^^ ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-20413.rs b/src/test/ui/issues/issue-20413.rs index a4345ccdfbe..138a235e675 100644 --- a/src/test/ui/issues/issue-20413.rs +++ b/src/test/ui/issues/issue-20413.rs @@ -1,5 +1,5 @@ trait Foo { - fn answer(self); + fn answer(self); } struct NoData<T>; @@ -7,18 +7,17 @@ struct NoData<T>; impl<T> Foo for T where NoData<T>: Foo { //~^ ERROR: overflow evaluating the requirement - //~| ERROR: overflow evaluating the requirement fn answer(self) { let val: NoData<T> = NoData; } } trait Bar { - fn answer(self); + fn answer(self); } trait Baz { - fn answer(self); + fn answer(self); } struct AlmostNoData<T>(Option<T>); @@ -27,7 +26,6 @@ struct EvenLessData<T>(Option<T>); impl<T> Bar for T where EvenLessData<T>: Baz { //~^ ERROR: overflow evaluating the requirement -//~| ERROR: overflow evaluating the requirement fn answer(self) { let val: EvenLessData<T> = EvenLessData(None); } @@ -35,7 +33,6 @@ impl<T> Bar for T where EvenLessData<T>: Baz { impl<T> Baz for T where AlmostNoData<T>: Bar { //~^ ERROR: overflow evaluating the requirement -//~| ERROR: overflow evaluating the requirement fn answer(self) { let val: NoData<T> = AlmostNoData(None); } diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr index 29352141404..ea493c58a33 100644 --- a/src/test/ui/issues/issue-20413.stderr +++ b/src/test/ui/issues/issue-20413.stderr @@ -22,102 +22,47 @@ LL | impl<T> Foo for T where NoData<T>: Foo { = note: 127 redundant requirements hidden = note: required because of the requirements on the impl of `Foo` for `NoData<T>` -error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo` - --> $DIR/issue-20413.rs:8:36 - | -LL | impl<T> Foo for T where NoData<T>: Foo { - | ^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) -note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/issue-20413.rs:8:9 - | -LL | impl<T> Foo for T where NoData<T>: Foo { - | ^^^ ^ - = note: 127 redundant requirements hidden - = note: required because of the requirements on the impl of `Foo` for `NoData<T>` - error[E0275]: overflow evaluating the requirement `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Baz` - --> $DIR/issue-20413.rs:28:42 + --> $DIR/issue-20413.rs:27:42 | LL | impl<T> Bar for T where EvenLessData<T>: Baz { | ^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/issue-20413.rs:28:9 + --> $DIR/issue-20413.rs:27:9 | LL | impl<T> Bar for T where EvenLessData<T>: Baz { | ^^^ ^ note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/issue-20413.rs:36:9 + --> $DIR/issue-20413.rs:34:9 | LL | impl<T> Baz for T where AlmostNoData<T>: Bar { | ^^^ ^ = note: 126 redundant requirements hidden = note: required because of the requirements on the impl of `Baz` for `EvenLessData<T>` -error[E0275]: overflow evaluating the requirement `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Baz` - --> $DIR/issue-20413.rs:28:42 - | -LL | impl<T> Bar for T where EvenLessData<T>: Baz { - | ^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) -note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/issue-20413.rs:28:9 - | -LL | impl<T> Bar for T where EvenLessData<T>: Baz { - | ^^^ ^ -note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/issue-20413.rs:36:9 - | -LL | impl<T> Baz for T where AlmostNoData<T>: Bar { - | ^^^ ^ - = note: 126 redundant requirements hidden - = note: required because of the requirements on the impl of `Baz` for `EvenLessData<T>` - -error[E0275]: overflow evaluating the requirement `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Bar` - --> $DIR/issue-20413.rs:36:42 - | -LL | impl<T> Baz for T where AlmostNoData<T>: Bar { - | ^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) -note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/issue-20413.rs:36:9 - | -LL | impl<T> Baz for T where AlmostNoData<T>: Bar { - | ^^^ ^ -note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/issue-20413.rs:28:9 - | -LL | impl<T> Bar for T where EvenLessData<T>: Baz { - | ^^^ ^ - = note: 126 redundant requirements hidden - = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<T>` - error[E0275]: overflow evaluating the requirement `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Bar` - --> $DIR/issue-20413.rs:36:42 + --> $DIR/issue-20413.rs:34:42 | LL | impl<T> Baz for T where AlmostNoData<T>: Bar { | ^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/issue-20413.rs:36:9 + --> $DIR/issue-20413.rs:34:9 | LL | impl<T> Baz for T where AlmostNoData<T>: Bar { | ^^^ ^ note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/issue-20413.rs:28:9 + --> $DIR/issue-20413.rs:27:9 | LL | impl<T> Bar for T where EvenLessData<T>: Baz { | ^^^ ^ = note: 126 redundant requirements hidden = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<T>` -error: aborting due to 7 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0275, E0392. For more information about an error, try `rustc --explain E0275`. diff --git a/src/test/ui/issues/issue-4265.stderr b/src/test/ui/issues/issue-4265.stderr index acdf963ed3b..27e83d49574 100644 --- a/src/test/ui/issues/issue-4265.stderr +++ b/src/test/ui/issues/issue-4265.stderr @@ -1,14 +1,11 @@ error[E0201]: duplicate definitions with name `bar`: --> $DIR/issue-4265.rs:10:5 | -LL | / fn bar() { -LL | | Foo { baz: 0 }.bar(); -LL | | } - | |_____- previous definition of `bar` here -LL | -LL | / fn bar() { -LL | | } - | |_____^ duplicate definition +LL | fn bar() { + | -------- previous definition of `bar` here +... +LL | fn bar() { + | ^^^^^^^^ duplicate definition error: aborting due to previous error diff --git a/src/test/ui/issues/issue-47511.rs b/src/test/ui/issues/issue-47511.rs index 98c141b6c6a..eb4860e75d7 100644 --- a/src/test/ui/issues/issue-47511.rs +++ b/src/test/ui/issues/issue-47511.rs @@ -1,5 +1,5 @@ // check-fail -// known-bug +// known-bug: #47511 // Regression test for #47511: anonymous lifetimes can appear // unconstrained in a return type, but only if they appear just once diff --git a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr index 33f6c498b6f..affb4e8d044 100644 --- a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr +++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr @@ -10,6 +10,28 @@ LL | struct Foo<T: 'static> { | +++++++++ error[E0309]: the parameter type `K` may not live long enough + --> $DIR/lifetime-doesnt-live-long-enough.rs:41:33 + | +LL | fn generic_in_parent<'a, L: X<&'a Nested<K>>>() { + | ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<K>` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | impl<K: 'a> Nested<K> { + | ++++ + +error[E0309]: the parameter type `M` may not live long enough + --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36 + | +LL | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() { + | ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<M>` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b + 'a>() { + | ++++ + +error[E0309]: the parameter type `K` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:24:19 | LL | fn foo<'a, L: X<&'a Nested<K>>>(); @@ -40,28 +62,6 @@ help: consider adding an explicit lifetime bound... LL | fn baz<'a, L: 'a, M: X<&'a Nested<L>>>() { | ++++ -error[E0309]: the parameter type `K` may not live long enough - --> $DIR/lifetime-doesnt-live-long-enough.rs:41:33 - | -LL | fn generic_in_parent<'a, L: X<&'a Nested<K>>>() { - | ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<K>` does not outlive the data it points at - | -help: consider adding an explicit lifetime bound... - | -LL | impl<K: 'a> Nested<K> { - | ++++ - -error[E0309]: the parameter type `M` may not live long enough - --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36 - | -LL | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() { - | ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<M>` does not outlive the data it points at - | -help: consider adding an explicit lifetime bound... - | -LL | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b + 'a>() { - | ++++ - error: aborting due to 6 previous errors Some errors have detailed explanations: E0309, E0310. diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.rs b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.rs index c79c1daf774..0e0d604ae04 100644 --- a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.rs +++ b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.rs @@ -20,43 +20,43 @@ fn main() { // AcqRel is always forbidden as a failure ordering let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Relaxed, Ordering::AcqRel); - //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Acquire, Ordering::AcqRel); - //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::AcqRel); - //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::AcqRel, Ordering::AcqRel); - //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::SeqCst, Ordering::AcqRel); - //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` // Release is always forbidden as a failure ordering let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Release); - //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Acquire, Ordering::Release); - //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Release, Ordering::Release); - //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::AcqRel, Ordering::Release); - //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::Release); - //~^ ERROR compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` // Release success order forbids failure order of Acquire or SeqCst let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::Acquire); - //~^ ERROR compare_exchange_weak's failure ordering may not be stronger + //~^ ERROR `compare_exchange_weak`'s success ordering must be at least as strong as let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::SeqCst); - //~^ ERROR compare_exchange_weak's failure ordering may not be stronger + //~^ ERROR `compare_exchange_weak`'s success ordering must be at least as strong as // Relaxed success order also forbids failure order of Acquire or SeqCst let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::SeqCst); - //~^ ERROR compare_exchange_weak's failure ordering may not be stronger + //~^ ERROR `compare_exchange_weak`'s success ordering must be at least as strong as let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Acquire); - //~^ ERROR compare_exchange_weak's failure ordering may not be stronger + //~^ ERROR `compare_exchange_weak`'s success ordering must be at least as strong as // Acquire/AcqRel forbids failure order of SeqCst let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Acquire, Ordering::SeqCst); - //~^ ERROR compare_exchange_weak's failure ordering may not be stronger + //~^ ERROR `compare_exchange_weak`'s success ordering must be at least as strong as let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::AcqRel, Ordering::SeqCst); - //~^ ERROR compare_exchange_weak's failure ordering may not be stronger + //~^ ERROR `compare_exchange_weak`'s success ordering must be at least as strong as } diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr index 13350ab0b9c..d5e53418b6f 100644 --- a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr +++ b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr @@ -1,131 +1,137 @@ -error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:22:67 | LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Relaxed, Ordering::AcqRel); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ invalid failure ordering | = note: `#[deny(invalid_atomic_ordering)]` on by default - = help: consider using ordering mode `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:24:67 | LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Acquire, Ordering::AcqRel); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:26:67 | LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::AcqRel); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering mode `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:28:66 | LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::AcqRel, Ordering::AcqRel); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:30:66 | LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::SeqCst, Ordering::AcqRel); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:34:67 | LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Release); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering mode `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:36:67 | LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Acquire, Ordering::Release); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:38:67 | LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Release, Ordering::Release); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering mode `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:40:66 | LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::AcqRel, Ordering::Release); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange_weak's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:42:66 | LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::Release); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange_weak's failure ordering may not be stronger than the success ordering of `Release` - --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:46:67 +error: `compare_exchange_weak`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:46:48 | LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::Acquire); - | ^^^^^^^^^^^^^^^^^ - | - = help: consider using ordering mode `Relaxed` instead + | ^^^^^^^^^^^^^^^^^ ----------------- `Acquire` failure ordering + | | + | `Release` success ordering + | help: consider using `AcqRel` success ordering instead -error: compare_exchange_weak's failure ordering may not be stronger than the success ordering of `Release` - --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:48:67 +error: `compare_exchange_weak`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:48:48 | LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::SeqCst); - | ^^^^^^^^^^^^^^^^ - | - = help: consider using ordering mode `Relaxed` instead + | ^^^^^^^^^^^^^^^^^ ---------------- `SeqCst` failure ordering + | | + | `Release` success ordering + | help: consider using `SeqCst` success ordering instead -error: compare_exchange_weak's failure ordering may not be stronger than the success ordering of `Relaxed` - --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:52:67 +error: `compare_exchange_weak`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:52:48 | LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::SeqCst); - | ^^^^^^^^^^^^^^^^ - | - = help: consider using ordering mode `Relaxed` instead + | ^^^^^^^^^^^^^^^^^ ---------------- `SeqCst` failure ordering + | | + | `Relaxed` success ordering + | help: consider using `SeqCst` success ordering instead -error: compare_exchange_weak's failure ordering may not be stronger than the success ordering of `Relaxed` - --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:54:67 +error: `compare_exchange_weak`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:54:48 | LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Acquire); - | ^^^^^^^^^^^^^^^^^ - | - = help: consider using ordering mode `Relaxed` instead + | ^^^^^^^^^^^^^^^^^ ----------------- `Acquire` failure ordering + | | + | `Relaxed` success ordering + | help: consider using `Acquire` success ordering instead -error: compare_exchange_weak's failure ordering may not be stronger than the success ordering of `Acquire` - --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:58:67 +error: `compare_exchange_weak`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:58:48 | LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Acquire, Ordering::SeqCst); - | ^^^^^^^^^^^^^^^^ - | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + | ^^^^^^^^^^^^^^^^^ ---------------- `SeqCst` failure ordering + | | + | `Acquire` success ordering + | help: consider using `SeqCst` success ordering instead -error: compare_exchange_weak's failure ordering may not be stronger than the success ordering of `AcqRel` - --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:60:66 +error: `compare_exchange_weak`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:60:48 | LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::AcqRel, Ordering::SeqCst); - | ^^^^^^^^^^^^^^^^ - | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + | ^^^^^^^^^^^^^^^^ ---------------- `SeqCst` failure ordering + | | + | `AcqRel` success ordering + | help: consider using `SeqCst` success ordering instead error: aborting due to 16 previous errors diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.rs b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.rs index 8ef3a400cf0..da98d854262 100644 --- a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.rs +++ b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.rs @@ -18,43 +18,43 @@ fn main() { // AcqRel is always forbidden as a failure ordering let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::AcqRel); - //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::AcqRel); - //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::AcqRel); - //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::AcqRel); - //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::AcqRel); - //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` // Release is always forbidden as a failure ordering let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Release); - //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::Release); - //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Release); - //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::Release); - //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::Release); - //~^ ERROR compare_exchange's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` // Release success order forbids failure order of Acquire or SeqCst let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Acquire); - //~^ ERROR compare_exchange's failure ordering may not be stronger + //~^ ERROR `compare_exchange`'s success ordering must be at least as strong as let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::SeqCst); - //~^ ERROR compare_exchange's failure ordering may not be stronger + //~^ ERROR `compare_exchange`'s success ordering must be at least as strong as // Relaxed success order also forbids failure order of Acquire or SeqCst let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::SeqCst); - //~^ ERROR compare_exchange's failure ordering may not be stronger + //~^ ERROR `compare_exchange`'s success ordering must be at least as strong as let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Acquire); - //~^ ERROR compare_exchange's failure ordering may not be stronger + //~^ ERROR `compare_exchange`'s success ordering must be at least as strong as // Acquire/AcqRel forbids failure order of SeqCst let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::SeqCst); - //~^ ERROR compare_exchange's failure ordering may not be stronger + //~^ ERROR `compare_exchange`'s success ordering must be at least as strong as let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::SeqCst); - //~^ ERROR compare_exchange's failure ordering may not be stronger + //~^ ERROR `compare_exchange`'s success ordering must be at least as strong as } diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.stderr b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.stderr index daedfec7430..41121a20dee 100644 --- a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.stderr +++ b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.stderr @@ -1,131 +1,137 @@ -error: compare_exchange's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange.rs:20:57 | LL | let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::AcqRel); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ invalid failure ordering | = note: `#[deny(invalid_atomic_ordering)]` on by default - = help: consider using ordering mode `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange.rs:22:57 | LL | let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::AcqRel); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange.rs:24:57 | LL | let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::AcqRel); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering mode `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange.rs:26:56 | LL | let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::AcqRel); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange.rs:28:56 | LL | let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::AcqRel); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange.rs:32:57 | LL | let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Release); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering mode `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange.rs:34:57 | LL | let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::Release); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange.rs:36:57 | LL | let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Release); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering mode `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange.rs:38:56 | LL | let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::Release); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange's failure ordering may not be `Release` or `AcqRel` +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write --> $DIR/lint-invalid-atomic-ordering-exchange.rs:40:56 | LL | let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::Release); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: compare_exchange's failure ordering may not be stronger than the success ordering of `Release` - --> $DIR/lint-invalid-atomic-ordering-exchange.rs:44:57 +error: `compare_exchange`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:44:38 | LL | let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Acquire); - | ^^^^^^^^^^^^^^^^^ - | - = help: consider using ordering mode `Relaxed` instead + | ^^^^^^^^^^^^^^^^^ ----------------- `Acquire` failure ordering + | | + | `Release` success ordering + | help: consider using `AcqRel` success ordering instead -error: compare_exchange's failure ordering may not be stronger than the success ordering of `Release` - --> $DIR/lint-invalid-atomic-ordering-exchange.rs:46:57 +error: `compare_exchange`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:46:38 | LL | let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::SeqCst); - | ^^^^^^^^^^^^^^^^ - | - = help: consider using ordering mode `Relaxed` instead + | ^^^^^^^^^^^^^^^^^ ---------------- `SeqCst` failure ordering + | | + | `Release` success ordering + | help: consider using `SeqCst` success ordering instead -error: compare_exchange's failure ordering may not be stronger than the success ordering of `Relaxed` - --> $DIR/lint-invalid-atomic-ordering-exchange.rs:50:57 +error: `compare_exchange`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:50:38 | LL | let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::SeqCst); - | ^^^^^^^^^^^^^^^^ - | - = help: consider using ordering mode `Relaxed` instead + | ^^^^^^^^^^^^^^^^^ ---------------- `SeqCst` failure ordering + | | + | `Relaxed` success ordering + | help: consider using `SeqCst` success ordering instead -error: compare_exchange's failure ordering may not be stronger than the success ordering of `Relaxed` - --> $DIR/lint-invalid-atomic-ordering-exchange.rs:52:57 +error: `compare_exchange`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:52:38 | LL | let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Acquire); - | ^^^^^^^^^^^^^^^^^ - | - = help: consider using ordering mode `Relaxed` instead + | ^^^^^^^^^^^^^^^^^ ----------------- `Acquire` failure ordering + | | + | `Relaxed` success ordering + | help: consider using `Acquire` success ordering instead -error: compare_exchange's failure ordering may not be stronger than the success ordering of `Acquire` - --> $DIR/lint-invalid-atomic-ordering-exchange.rs:56:57 +error: `compare_exchange`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:56:38 | LL | let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::SeqCst); - | ^^^^^^^^^^^^^^^^ - | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + | ^^^^^^^^^^^^^^^^^ ---------------- `SeqCst` failure ordering + | | + | `Acquire` success ordering + | help: consider using `SeqCst` success ordering instead -error: compare_exchange's failure ordering may not be stronger than the success ordering of `AcqRel` - --> $DIR/lint-invalid-atomic-ordering-exchange.rs:58:56 +error: `compare_exchange`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:58:38 | LL | let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::SeqCst); - | ^^^^^^^^^^^^^^^^ - | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + | ^^^^^^^^^^^^^^^^ ---------------- `SeqCst` failure ordering + | | + | `AcqRel` success ordering + | help: consider using `SeqCst` success ordering instead error: aborting due to 16 previous errors diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.rs b/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.rs index 938ca0359f8..73eda182aa8 100644 --- a/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.rs +++ b/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.rs @@ -18,43 +18,43 @@ fn main() { // AcqRel is always forbidden as a failure ordering let _ = x.fetch_update(Ordering::Relaxed, Ordering::AcqRel, |old| Some(old + 1)); - //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` let _ = x.fetch_update(Ordering::Acquire, Ordering::AcqRel, |old| Some(old + 1)); - //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` let _ = x.fetch_update(Ordering::Release, Ordering::AcqRel, |old| Some(old + 1)); - //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` let _ = x.fetch_update(Ordering::AcqRel, Ordering::AcqRel, |old| Some(old + 1)); - //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` let _ = x.fetch_update(Ordering::SeqCst, Ordering::AcqRel, |old| Some(old + 1)); - //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` // Release is always forbidden as a failure ordering let _ = x.fetch_update(Ordering::Relaxed, Ordering::Release, |old| Some(old + 1)); - //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` let _ = x.fetch_update(Ordering::Acquire, Ordering::Release, |old| Some(old + 1)); - //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` let _ = x.fetch_update(Ordering::Release, Ordering::Release, |old| Some(old + 1)); - //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` let _ = x.fetch_update(Ordering::AcqRel, Ordering::Release, |old| Some(old + 1)); - //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` let _ = x.fetch_update(Ordering::SeqCst, Ordering::Release, |old| Some(old + 1)); - //~^ ERROR fetch_update's failure ordering may not be `Release` or `AcqRel` + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` // Release success order forbids failure order of Acquire or SeqCst let _ = x.fetch_update(Ordering::Release, Ordering::Acquire, |old| Some(old + 1)); - //~^ ERROR fetch_update's failure ordering may not be stronger + //~^ ERROR `fetch_update`'s success ordering must be at least as strong as let _ = x.fetch_update(Ordering::Release, Ordering::SeqCst, |old| Some(old + 1)); - //~^ ERROR fetch_update's failure ordering may not be stronger + //~^ ERROR `fetch_update`'s success ordering must be at least as strong as // Relaxed success order also forbids failure order of Acquire or SeqCst let _ = x.fetch_update(Ordering::Relaxed, Ordering::SeqCst, |old| Some(old + 1)); - //~^ ERROR fetch_update's failure ordering may not be stronger + //~^ ERROR `fetch_update`'s success ordering must be at least as strong as let _ = x.fetch_update(Ordering::Relaxed, Ordering::Acquire, |old| Some(old + 1)); - //~^ ERROR fetch_update's failure ordering may not be stronger + //~^ ERROR `fetch_update`'s success ordering must be at least as strong as // Acquire/AcqRel forbids failure order of SeqCst let _ = x.fetch_update(Ordering::Acquire, Ordering::SeqCst, |old| Some(old + 1)); - //~^ ERROR fetch_update's failure ordering may not be stronger + //~^ ERROR `fetch_update`'s success ordering must be at least as strong as let _ = x.fetch_update(Ordering::AcqRel, Ordering::SeqCst, |old| Some(old + 1)); - //~^ ERROR fetch_update's failure ordering may not be stronger + //~^ ERROR `fetch_update`'s success ordering must be at least as strong as } diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr b/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr index dabc1da7e55..7bea56d57fb 100644 --- a/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr +++ b/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr @@ -1,131 +1,137 @@ -error: fetch_update's failure ordering may not be `Release` or `AcqRel` +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:20:47 | LL | let _ = x.fetch_update(Ordering::Relaxed, Ordering::AcqRel, |old| Some(old + 1)); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ invalid failure ordering | = note: `#[deny(invalid_atomic_ordering)]` on by default - = help: consider using ordering mode `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: fetch_update's failure ordering may not be `Release` or `AcqRel` +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:22:47 | LL | let _ = x.fetch_update(Ordering::Acquire, Ordering::AcqRel, |old| Some(old + 1)); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: fetch_update's failure ordering may not be `Release` or `AcqRel` +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:24:47 | LL | let _ = x.fetch_update(Ordering::Release, Ordering::AcqRel, |old| Some(old + 1)); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering mode `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: fetch_update's failure ordering may not be `Release` or `AcqRel` +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:26:46 | LL | let _ = x.fetch_update(Ordering::AcqRel, Ordering::AcqRel, |old| Some(old + 1)); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: fetch_update's failure ordering may not be `Release` or `AcqRel` +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:28:46 | LL | let _ = x.fetch_update(Ordering::SeqCst, Ordering::AcqRel, |old| Some(old + 1)); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: fetch_update's failure ordering may not be `Release` or `AcqRel` +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:32:47 | LL | let _ = x.fetch_update(Ordering::Relaxed, Ordering::Release, |old| Some(old + 1)); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering mode `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: fetch_update's failure ordering may not be `Release` or `AcqRel` +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:34:47 | LL | let _ = x.fetch_update(Ordering::Acquire, Ordering::Release, |old| Some(old + 1)); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: fetch_update's failure ordering may not be `Release` or `AcqRel` +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:36:47 | LL | let _ = x.fetch_update(Ordering::Release, Ordering::Release, |old| Some(old + 1)); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering mode `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: fetch_update's failure ordering may not be `Release` or `AcqRel` +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:38:46 | LL | let _ = x.fetch_update(Ordering::AcqRel, Ordering::Release, |old| Some(old + 1)); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: fetch_update's failure ordering may not be `Release` or `AcqRel` +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:40:46 | LL | let _ = x.fetch_update(Ordering::SeqCst, Ordering::Release, |old| Some(old + 1)); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ invalid failure ordering | - = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` instead + = help: consider using `Acquire` or `Relaxed` failure ordering instead -error: fetch_update's failure ordering may not be stronger than the success ordering of `Release` - --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:44:47 +error: `fetch_update`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:44:28 | LL | let _ = x.fetch_update(Ordering::Release, Ordering::Acquire, |old| Some(old + 1)); - | ^^^^^^^^^^^^^^^^^ - | - = help: consider using ordering mode `Relaxed` instead + | ^^^^^^^^^^^^^^^^^ ----------------- `Acquire` failure ordering + | | + | `Release` success ordering + | help: consider using `AcqRel` success ordering instead -error: fetch_update's failure ordering may not be stronger than the success ordering of `Release` - --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:46:47 +error: `fetch_update`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:46:28 | LL | let _ = x.fetch_update(Ordering::Release, Ordering::SeqCst, |old| Some(old + 1)); - | ^^^^^^^^^^^^^^^^ - | - = help: consider using ordering mode `Relaxed` instead + | ^^^^^^^^^^^^^^^^^ ---------------- `SeqCst` failure ordering + | | + | `Release` success ordering + | help: consider using `SeqCst` success ordering instead -error: fetch_update's failure ordering may not be stronger than the success ordering of `Relaxed` - --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:50:47 +error: `fetch_update`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:50:28 | LL | let _ = x.fetch_update(Ordering::Relaxed, Ordering::SeqCst, |old| Some(old + 1)); - | ^^^^^^^^^^^^^^^^ - | - = help: consider using ordering mode `Relaxed` instead + | ^^^^^^^^^^^^^^^^^ ---------------- `SeqCst` failure ordering + | | + | `Relaxed` success ordering + | help: consider using `SeqCst` success ordering instead -error: fetch_update's failure ordering may not be stronger than the success ordering of `Relaxed` - --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:52:47 +error: `fetch_update`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:52:28 | LL | let _ = x.fetch_update(Ordering::Relaxed, Ordering::Acquire, |old| Some(old + 1)); - | ^^^^^^^^^^^^^^^^^ - | - = help: consider using ordering mode `Relaxed` instead + | ^^^^^^^^^^^^^^^^^ ----------------- `Acquire` failure ordering + | | + | `Relaxed` success ordering + | help: consider using `Acquire` success ordering instead -error: fetch_update's failure ordering may not be stronger than the success ordering of `Acquire` - --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:56:47 +error: `fetch_update`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:56:28 | LL | let _ = x.fetch_update(Ordering::Acquire, Ordering::SeqCst, |old| Some(old + 1)); - | ^^^^^^^^^^^^^^^^ - | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + | ^^^^^^^^^^^^^^^^^ ---------------- `SeqCst` failure ordering + | | + | `Acquire` success ordering + | help: consider using `SeqCst` success ordering instead -error: fetch_update's failure ordering may not be stronger than the success ordering of `AcqRel` - --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:58:46 +error: `fetch_update`'s success ordering must be at least as strong as its failure ordering + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:58:28 | LL | let _ = x.fetch_update(Ordering::AcqRel, Ordering::SeqCst, |old| Some(old + 1)); - | ^^^^^^^^^^^^^^^^ - | - = help: consider using ordering modes `Acquire` or `Relaxed` instead + | ^^^^^^^^^^^^^^^^ ---------------- `SeqCst` failure ordering + | | + | `AcqRel` success ordering + | help: consider using `SeqCst` success ordering instead error: aborting due to 16 previous errors diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs deleted file mode 100644 index 1db9d33c72a..00000000000 --- a/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs +++ /dev/null @@ -1,9 +0,0 @@ -// check-pass -// compile-flags: -Z unpretty=expanded - -#![feature(core_intrinsics, generic_assert, generic_assert_internals)] - -fn main() { - let elem = 1i32; - assert!(elem == 1); -} diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout b/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout deleted file mode 100644 index a590eb32232..00000000000 --- a/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout +++ /dev/null @@ -1,29 +0,0 @@ -#![feature(prelude_import)] -#![no_std] -// check-pass -// compile-flags: -Z unpretty=expanded - -#![feature(core_intrinsics, generic_assert, generic_assert_internals)] -#[prelude_import] -use ::std::prelude::rust_2015::*; -#[macro_use] -extern crate std; - -fn main() { - let elem = 1i32; - { - #[allow(unused_imports)] - use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; - let mut __capture0 = ::core::asserting::Capture::new(); - let __local_bind0 = &elem; - if !(*{ - (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); - __local_bind0 - } == 1) { - { - ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem == 1\nWith captures:\n elem = ", - "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) - } - } - }; -} diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs new file mode 100644 index 00000000000..5ec84b08ff8 --- /dev/null +++ b/src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs @@ -0,0 +1,32 @@ +// check-pass +// compile-flags: -Z unpretty=expanded + +#![feature(core_intrinsics, generic_assert, generic_assert_internals)] + +fn arbitrary_consuming_method_for_demonstration_purposes() { + let elem = 1i32; + assert!(elem as usize); +} + +fn addr_of() { + let elem = 1i32; + assert!(&elem); +} + +fn binary() { + let elem = 1i32; + assert!(elem == 1); + assert!(elem >= 1); + assert!(elem > 0); + assert!(elem < 3); + assert!(elem <= 3); + assert!(elem != 3); +} + +fn unary() { + let elem = &1i32; + assert!(*elem); +} + +fn main() { +} diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout b/src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout new file mode 100644 index 00000000000..90f858f80e6 --- /dev/null +++ b/src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout @@ -0,0 +1,147 @@ +#![feature(prelude_import)] +#![no_std] +// check-pass +// compile-flags: -Z unpretty=expanded + +#![feature(core_intrinsics, generic_assert, generic_assert_internals)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +fn arbitrary_consuming_method_for_demonstration_purposes() { + let elem = 1i32; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!(*{ + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + __local_bind0 + } as usize)) { + + + + + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem as usize\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; +} +fn addr_of() { + let elem = 1i32; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!&*__local_bind0) { + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: &elem\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; +} +fn binary() { + let elem = 1i32; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!(*__local_bind0 == 1)) { + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem == 1\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!(*__local_bind0 >= 1)) { + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem >= 1\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!(*__local_bind0 > 0)) { + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem > 0\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!(*__local_bind0 < 3)) { + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem < 3\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!(*__local_bind0 <= 3)) { + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem <= 3\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!(*__local_bind0 != 3)) { + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem != 3\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; +} +fn unary() { + let elem = &1i32; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!**__local_bind0) { + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: *elem\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; +} +fn main() {} diff --git a/src/test/ui/methods/method-macro-backtrace.stderr b/src/test/ui/methods/method-macro-backtrace.stderr index 7860365476a..7ae00835c96 100644 --- a/src/test/ui/methods/method-macro-backtrace.stderr +++ b/src/test/ui/methods/method-macro-backtrace.stderr @@ -2,9 +2,9 @@ error[E0201]: duplicate definitions with name `bar`: --> $DIR/method-macro-backtrace.rs:22:5 | LL | fn bar(&self) { } - | ----------------- previous definition of `bar` here + | ------------- previous definition of `bar` here LL | fn bar(&self) { } - | ^^^^^^^^^^^^^^^^^ duplicate definition + | ^^^^^^^^^^^^^ duplicate definition error: aborting due to previous error diff --git a/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr b/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr index 40b4b42f742..b77c8c7fd5b 100644 --- a/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr +++ b/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr @@ -1,3 +1,29 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/adt-param-with-implicit-sized-bound.rs:25:9 + | +LL | struct Struct5<T: ?Sized>{ + | - this type parameter needs to be `std::marker::Sized` +LL | _t: X<T>, + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `X` + --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10 + | +LL | struct X<T>(T); + | ^ required by this bound in `X` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>` + --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10 + | +LL | struct X<T>(T); + | ^ - ...if indirection were used here: `Box<T>` + | | + | this could be changed to `T: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - struct Struct5<T: ?Sized>{ +LL + struct Struct5<T>{ + | + error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/adt-param-with-implicit-sized-bound.rs:2:19 | @@ -81,32 +107,6 @@ help: consider relaxing the implicit `Sized` restriction LL | struct Struct4<T: ?Sized>{ | ++++++++ -error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/adt-param-with-implicit-sized-bound.rs:25:9 - | -LL | struct Struct5<T: ?Sized>{ - | - this type parameter needs to be `std::marker::Sized` -LL | _t: X<T>, - | ^^^^ doesn't have a size known at compile-time - | -note: required by a bound in `X` - --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10 - | -LL | struct X<T>(T); - | ^ required by this bound in `X` -help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>` - --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10 - | -LL | struct X<T>(T); - | ^ - ...if indirection were used here: `Box<T>` - | | - | this could be changed to `T: ?Sized`... -help: consider removing the `?Sized` bound to make the type parameter `Sized` - | -LL - struct Struct5<T: ?Sized>{ -LL + struct Struct5<T>{ - | - error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/auxiliary/not-object-safe.rs b/src/test/ui/suggestions/auxiliary/not-object-safe.rs new file mode 100644 index 00000000000..7c9829b823e --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/not-object-safe.rs @@ -0,0 +1,6 @@ +use std::sync::Arc; + +pub trait A { + fn f(); + fn f2(self: &Arc<Self>); +} diff --git a/src/test/ui/suggestions/issue-98500.rs b/src/test/ui/suggestions/issue-98500.rs new file mode 100644 index 00000000000..a2717fd9206 --- /dev/null +++ b/src/test/ui/suggestions/issue-98500.rs @@ -0,0 +1,14 @@ +// aux-build:not-object-safe.rs + +extern crate not_object_safe; + +pub trait B where + Self: not_object_safe::A, +{ + fn f2(&self); +} + +struct S(Box<dyn B>); +//~^ ERROR the trait `B` cannot be made into an object + +fn main() {} diff --git a/src/test/ui/suggestions/issue-98500.stderr b/src/test/ui/suggestions/issue-98500.stderr new file mode 100644 index 00000000000..e7251d735e3 --- /dev/null +++ b/src/test/ui/suggestions/issue-98500.stderr @@ -0,0 +1,24 @@ +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/issue-98500.rs:11:14 + | +LL | struct S(Box<dyn B>); + | ^^^^^ `B` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/auxiliary/not-object-safe.rs:4:8 + | +LL | fn f(); + | ^ ...because associated function `f` has no `self` parameter +LL | fn f2(self: &Arc<Self>); + | ^^ ...because method `f2`'s `self` parameter cannot be dispatched on + | + ::: $DIR/issue-98500.rs:5:11 + | +LL | pub trait B where + | - this trait cannot be made into an object... + = help: consider moving `f` to another trait + = help: consider moving `f2` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed index 73bb6725f5a..69487c565c9 100644 --- a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed +++ b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed @@ -2,7 +2,7 @@ #![allow(unused_variables, dead_code)] trait Trait { - fn foo(&self) where Self: Other, Self: Sized, { } + fn foo(&self) where Self: Other, Self: Sized { } fn bar(self: &Self) {} //~ ERROR invalid `self` parameter type } diff --git a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr index 74237e6e6c6..c0dc71df06e 100644 --- a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr +++ b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr @@ -1,12 +1,3 @@ -error[E0307]: invalid `self` parameter type: () - --> $DIR/object-unsafe-trait-should-use-where-sized.rs:6:18 - | -LL | fn bar(self: ()) {} - | ^^ - | - = note: type of `self` must be `Self` or a type that dereferences to it - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) - error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:12 | @@ -28,13 +19,22 @@ LL | fn foo(&self) where Self: Other, { } | +++++ help: alternatively, consider constraining `foo` so it does not apply to trait objects | -LL | fn foo() where Self: Other, Self: Sized, { } - | +++++++++++++ +LL | fn foo() where Self: Other, Self: Sized { } + | ~~~~~~~~~~~~~ help: consider changing method `bar`'s `self` parameter to be `&self` | LL | fn bar(self: &Self) {} | ~~~~~ +error[E0307]: invalid `self` parameter type: () + --> $DIR/object-unsafe-trait-should-use-where-sized.rs:6:18 + | +LL | fn bar(self: ()) {} + | ^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) + error: aborting due to 2 previous errors Some errors have detailed explanations: E0038, E0307. diff --git a/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.rs b/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.rs index 288b2098b4c..fd975aaaee4 100644 --- a/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.rs +++ b/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.rs @@ -1,4 +1,4 @@ -// known-bug +// known-bug: #93008 // build-fail // failure-status: 101 // compile-flags:--crate-type=lib -Zmir-opt-level=3 diff --git a/src/test/ui/traits/alias/issue-83613.stderr b/src/test/ui/traits/alias/issue-83613.stderr index bbc240b6aec..b9d93160192 100644 --- a/src/test/ui/traits/alias/issue-83613.stderr +++ b/src/test/ui/traits/alias/issue-83613.stderr @@ -1,3 +1,11 @@ +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType` + --> $DIR/issue-83613.rs:10:1 + | +LL | impl<T: Send> AnotherTrait for T {} + | -------------------------------- first implementation here +LL | impl AnotherTrait for OpaqueType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType` + error: cannot implement trait on type alias impl trait --> $DIR/issue-83613.rs:10:23 | @@ -10,14 +18,6 @@ note: type alias impl trait defined here LL | type OpaqueType = impl OpaqueTrait; | ^^^^^^^^^^^^^^^^ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType` - --> $DIR/issue-83613.rs:10:1 - | -LL | impl<T: Send> AnotherTrait for T {} - | -------------------------------- first implementation here -LL | impl AnotherTrait for OpaqueType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType` - error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/traits/issue-78372.rs b/src/test/ui/traits/issue-78372.rs index 77a8c92c81c..92f9f4b467a 100644 --- a/src/test/ui/traits/issue-78372.rs +++ b/src/test/ui/traits/issue-78372.rs @@ -4,7 +4,6 @@ impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} //~ ERROR cannot find type `U` //~^ ERROR cannot find type `MISC` in this scope //~| ERROR use of unstable library feature 'dispatch_from_dyn' //~| ERROR the trait `DispatchFromDyn` may only be implemented for a coercion between structures -//~| ERROR type parameter `T` must be covered by another type when it appears before the first trait Foo: X<u32> {} trait X<T> { fn foo(self: Smaht<Self, T>); diff --git a/src/test/ui/traits/issue-78372.stderr b/src/test/ui/traits/issue-78372.stderr index 49a9f479368..7574c9107d9 100644 --- a/src/test/ui/traits/issue-78372.stderr +++ b/src/test/ui/traits/issue-78372.stderr @@ -50,22 +50,13 @@ LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} | = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable -error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Smaht<[type error], [type error]>`) - --> $DIR/issue-78372.rs:3:6 - | -LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} - | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Smaht<[type error], [type error]>`) - | - = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type - = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last - error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures --> $DIR/issue-78372.rs:3:1 | LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0210, E0378, E0412, E0658. -For more information about an error, try `rustc --explain E0210`. +Some errors have detailed explanations: E0378, E0412, E0658. +For more information about an error, try `rustc --explain E0378`. diff --git a/src/test/ui/traits/issue-8153.stderr b/src/test/ui/traits/issue-8153.stderr index 4389c3dc288..b76bbc0235f 100644 --- a/src/test/ui/traits/issue-8153.stderr +++ b/src/test/ui/traits/issue-8153.stderr @@ -2,9 +2,9 @@ error[E0201]: duplicate definitions with name `bar`: --> $DIR/issue-8153.rs:11:5 | LL | fn bar(&self) -> isize {1} - | -------------------------- previous definition of `bar` here + | ---------------------- previous definition of `bar` here LL | fn bar(&self) -> isize {2} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition + | ^^^^^^^^^^^^^^^^^^^^^^ duplicate definition error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs index 179f525de52..328096d44b4 100644 --- a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs +++ b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs @@ -1,4 +1,4 @@ -// known-bug +// known-bug: #96572 // compile-flags: --edition=2021 --crate-type=lib // rustc-env:RUST_BACKTRACE=0 diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs index 9c4e6c5496f..067ed7ea1e5 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -1,7 +1,7 @@ // Regression test for issue #57611 // Ensures that we don't ICE // FIXME: This should compile, but it currently doesn't -// known-bug +// known-bug: unknown #![feature(trait_alias)] #![feature(type_alias_impl_trait)] diff --git a/src/test/ui/union/issue-81199.stderr b/src/test/ui/union/issue-81199.stderr index f26bfe3a0b0..5bb98675361 100644 --- a/src/test/ui/union/issue-81199.stderr +++ b/src/test/ui/union/issue-81199.stderr @@ -1,28 +1,18 @@ -error[E0277]: the trait bound `T: Pointee` is not satisfied in `PtrComponents<T>` +error[E0277]: the trait bound `T: Pointee` is not satisfied --> $DIR/issue-81199.rs:5:17 | LL | components: PtrComponents<T>, - | ^^^^^^^^^^^^^^^^ within `PtrComponents<T>`, the trait `Pointee` is not implemented for `T` + | ^^^^^^^^^^^^^^^^ the trait `Pointee` is not implemented for `T` | -note: required because it appears within the type `PtrComponents<T>` - --> $DIR/issue-81199.rs:10:8 +note: required by a bound in `PtrComponents` + --> $DIR/issue-81199.rs:10:25 | LL | struct PtrComponents<T: Pointee + ?Sized> { - | ^^^^^^^^^^^^^ - = note: no field of a union may have a dynamically sized type - = help: change the field's type to have a statically known size + | ^^^^^^^ required by this bound in `PtrComponents` help: consider further restricting this bound | LL | union PtrRepr<T: ?Sized + Pointee> { | +++++++++ -help: borrowed types always have a statically known size - | -LL | components: &PtrComponents<T>, - | + -help: the `Box` type always has a statically known size and allocates its contents in the heap - | -LL | components: Box<PtrComponents<T>>, - | ++++ + error: aborting due to previous error diff --git a/src/test/ui/wf/issue-96810.rs b/src/test/ui/wf/issue-96810.rs new file mode 100644 index 00000000000..c2948086b20 --- /dev/null +++ b/src/test/ui/wf/issue-96810.rs @@ -0,0 +1,12 @@ +struct S<T: Tr>(T::Assoc); + +trait Tr { + type Assoc; +} + +struct Hoge<K> { + s: S<K>, //~ ERROR the trait bound `K: Tr` is not satisfied + a: u32, +} + +fn main() {} diff --git a/src/test/ui/wf/issue-96810.stderr b/src/test/ui/wf/issue-96810.stderr new file mode 100644 index 00000000000..1407e62b1e1 --- /dev/null +++ b/src/test/ui/wf/issue-96810.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `K: Tr` is not satisfied + --> $DIR/issue-96810.rs:8:8 + | +LL | s: S<K>, + | ^^^^ the trait `Tr` is not implemented for `K` + | +note: required by a bound in `S` + --> $DIR/issue-96810.rs:1:13 + | +LL | struct S<T: Tr>(T::Assoc); + | ^^ required by this bound in `S` +help: consider restricting type parameter `K` + | +LL | struct Hoge<K: Tr> { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs index f447940ea3b..8ae84dbb3dc 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_sugg_for_edges; +use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_trait_method; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; @@ -14,17 +14,14 @@ use super::MAP_FLATTEN; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, map_arg: &Expr<'_>, map_span: Span) { if let Some((caller_ty_name, method_to_use)) = try_get_caller_ty_name_and_method_name(cx, expr, recv, map_arg) { let mut applicability = Applicability::MachineApplicable; - let help_msgs = [ - &format!("try replacing `map` with `{}`", method_to_use), - "and remove the `.flatten()`", - ]; + let closure_snippet = snippet_with_applicability(cx, map_arg.span, "..", &mut applicability); - span_lint_and_sugg_for_edges( + span_lint_and_sugg( cx, MAP_FLATTEN, expr.span.with_lo(map_span.lo()), &format!("called `map(..).flatten()` on `{}`", caller_ty_name), - &help_msgs, + &format!("try replacing `map` with `{}` and remove the `.flatten()`", method_to_use), format!("{}({})", method_to_use, closure_snippet), applicability, ); diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs index 448dc4e6147..3d1208824fa 100644 --- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs +++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs @@ -4,7 +4,6 @@ use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_mac use clippy_utils::ty::{implements_trait, match_type}; use clippy_utils::{contains_return, is_trait_item, last_path_segment, paths}; use if_chain::if_chain; -use rustc_errors::emitter::MAX_SUGGESTION_HIGHLIGHT_LINES; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -33,7 +32,6 @@ pub(super) fn check<'tcx>( arg: &hir::Expr<'_>, or_has_args: bool, span: Span, - method_span: Span, ) -> bool { let is_default_default = || is_trait_item(cx, fun, sym::Default); @@ -56,19 +54,14 @@ pub(super) fn check<'tcx>( then { let mut applicability = Applicability::MachineApplicable; let hint = "unwrap_or_default()"; - let mut sugg_span = span; + let sugg_span = span; - let mut sugg: String = format!( + let sugg: String = format!( "{}.{}", snippet_with_applicability(cx, self_expr.span, "..", &mut applicability), hint ); - if sugg.lines().count() > MAX_SUGGESTION_HIGHLIGHT_LINES { - sugg_span = method_span.with_hi(span.hi()); - sugg = hint.to_string(); - } - span_lint_and_sugg( cx, OR_FUN_CALL, @@ -178,7 +171,7 @@ pub(super) fn check<'tcx>( match inner_arg.kind { hir::ExprKind::Call(fun, or_args) => { let or_has_args = !or_args.is_empty(); - if !check_unwrap_or_default(cx, name, fun, self_arg, arg, or_has_args, expr.span, method_span) { + if !check_unwrap_or_default(cx, name, fun, self_arg, arg, or_has_args, expr.span) { let fun_span = if or_has_args { None } else { Some(fun.span) }; check_general_case(cx, name, method_span, self_arg, arg, expr.span, fun_span); } diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs index 99e9e3275ab..2564099f4db 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -112,7 +112,6 @@ const LINT_EMISSION_FUNCTIONS: [&[&str]; 8] = [ &["clippy_utils", "diagnostics", "span_lint_and_sugg"], &["clippy_utils", "diagnostics", "span_lint_and_then"], &["clippy_utils", "diagnostics", "span_lint_hir_and_then"], - &["clippy_utils", "diagnostics", "span_lint_and_sugg_for_edges"], ]; const SUGGESTION_DIAGNOSTIC_BUILDER_METHODS: [(&str, bool); 9] = [ ("span_suggestion", false), diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index 39595f589c7..7f55db3b31f 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -8,7 +8,7 @@ //! Thank you! //! ~The `INTERNAL_METADATA_COLLECTOR` lint -use rustc_errors::{emitter::MAX_SUGGESTION_HIGHLIGHT_LINES, Applicability, Diagnostic, MultiSpan}; +use rustc_errors::{Applicability, Diagnostic, MultiSpan}; use rustc_hir::HirId; use rustc_lint::{LateContext, Lint, LintContext}; use rustc_span::source_map::Span; @@ -219,95 +219,6 @@ pub fn span_lint_and_sugg<'a, T: LintContext>( }); } -/// Like [`span_lint_and_sugg`] with a focus on the edges. The output will either -/// emit single span or multispan suggestion depending on the number of its lines. -/// -/// If the given suggestion string has more lines than the maximum display length defined by -/// [`MAX_SUGGESTION_HIGHLIGHT_LINES`][`rustc_errors::emitter::MAX_SUGGESTION_HIGHLIGHT_LINES`], -/// this function will split the suggestion and span to showcase the change for the top and -/// bottom edge of the code. For normal suggestions, in one display window, the help message -/// will be combined with a colon. -/// -/// Multipart suggestions like the one being created here currently cannot be -/// applied by rustfix (See [rustfix#141](https://github.com/rust-lang/rustfix/issues/141)). -/// Testing rustfix with this lint emission function might require a file with -/// suggestions that can be fixed and those that can't. See -/// [clippy#8520](https://github.com/rust-lang/rust-clippy/pull/8520/files) for -/// an example and of this. -/// -/// # Example for a long suggestion -/// -/// ```text -/// error: called `map(..).flatten()` on `Option` -/// --> $DIR/map_flatten.rs:8:10 -/// | -/// LL | .map(|x| { -/// | __________^ -/// LL | | if x <= 5 { -/// LL | | Some(x) -/// LL | | } else { -/// ... | -/// LL | | }) -/// LL | | .flatten(); -/// | |__________________^ -/// | -/// = note: `-D clippy::map-flatten` implied by `-D warnings` -/// help: try replacing `map` with `and_then` -/// | -/// LL ~ .and_then(|x| { -/// LL + if x <= 5 { -/// LL + Some(x) -/// | -/// help: and remove the `.flatten()` -/// | -/// LL + None -/// LL + } -/// LL ~ }); -/// | -/// ``` -pub fn span_lint_and_sugg_for_edges( - cx: &LateContext<'_>, - lint: &'static Lint, - sp: Span, - msg: &str, - helps: &[&str; 2], - sugg: String, - applicability: Applicability, -) { - span_lint_and_then(cx, lint, sp, msg, |diag| { - let sugg_lines_count = sugg.lines().count(); - if sugg_lines_count > MAX_SUGGESTION_HIGHLIGHT_LINES { - let sm = cx.sess().source_map(); - if let (Ok(line_upper), Ok(line_bottom)) = - (sm.lookup_line(sp.lo()), sm.lookup_line(sp.hi())) - { - let split_idx = MAX_SUGGESTION_HIGHLIGHT_LINES / 2; - let span_upper = sm.span_until_char( - sp.with_hi(line_upper.sf.lines(|lines| lines[line_upper.line + split_idx])), - '\n', - ); - let span_bottom = sp.with_lo(line_bottom.sf.lines(|lines| lines[line_bottom.line - split_idx])); - - let sugg_lines_vec = sugg.lines().collect::<Vec<&str>>(); - let sugg_upper = sugg_lines_vec[..split_idx].join("\n"); - let sugg_bottom = sugg_lines_vec[sugg_lines_count - split_idx..].join("\n"); - - diag.span_suggestion(span_upper, helps[0], sugg_upper, applicability); - diag.span_suggestion(span_bottom, helps[1], sugg_bottom, applicability); - - return; - } - } - diag.span_suggestion_with_style( - sp, - &helps.join(", "), - sugg, - applicability, - rustc_errors::SuggestionStyle::ShowAlways, - ); - }); -} - /// Create a suggestion made from several `span → replacement`. /// /// Note: in the JSON format (used by `compiletest_rs`), the help message will diff --git a/src/tools/clippy/tests/ui/map_flatten.stderr b/src/tools/clippy/tests/ui/map_flatten.stderr index c9c60df838f..4b2630d6858 100644 --- a/src/tools/clippy/tests/ui/map_flatten.stderr +++ b/src/tools/clippy/tests/ui/map_flatten.stderr @@ -12,14 +12,12 @@ LL | | .flatten(); | |__________________^ | = note: `-D clippy::map-flatten` implied by `-D warnings` -help: try replacing `map` with `and_then` +help: try replacing `map` with `and_then` and remove the `.flatten()` | LL ~ .and_then(|x| { LL + if x <= 5 { LL + Some(x) - | -help: and remove the `.flatten()` - | +LL + } else { LL + None LL + } LL ~ }); @@ -38,14 +36,12 @@ LL | | }) LL | | .flatten(); | |__________________^ | -help: try replacing `map` with `and_then` +help: try replacing `map` with `and_then` and remove the `.flatten()` | LL ~ .and_then(|x| { LL + if x == 1 { LL + Ok(x) - | -help: and remove the `.flatten()` - | +LL + } else { LL + Err(0) LL + } LL ~ }); @@ -64,14 +60,13 @@ LL | | }) LL | | .flatten(); | |__________________^ | -help: try replacing `map` with `and_then` +help: try replacing `map` with `and_then` and remove the `.flatten()` | LL ~ .and_then(|res| { LL + if res > 0 { LL + do_something(); - | -help: and remove the `.flatten()` - | +LL + Ok(res) +LL + } else { LL + Err(0) LL + } LL ~ }); @@ -90,14 +85,12 @@ LL | | }) LL | | .flatten() | |__________________^ | -help: try replacing `map` with `filter_map` +help: try replacing `map` with `filter_map` and remove the `.flatten()` | LL ~ .filter_map(|some_value| { LL + if some_value > 3 { LL + Some(some_value) - | -help: and remove the `.flatten()` - | +LL + } else { LL + None LL + } LL + }) diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.fixed b/src/tools/clippy/tests/ui/map_flatten_fixable.fixed index 928e5bd509c..e9b41354c58 100644 --- a/src/tools/clippy/tests/ui/map_flatten_fixable.fixed +++ b/src/tools/clippy/tests/ui/map_flatten_fixable.fixed @@ -59,8 +59,6 @@ fn issue8878() { .and_then(|_| { // we need some newlines // so that the span is big enough -// we need some newlines -// so that the span is big enough // for a splitted output of the diagnostic Some("") // whitespace beforehand is important as well diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr index 828e24acaad..f3b82ad08d0 100644 --- a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr +++ b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr @@ -2,79 +2,45 @@ error: called `map(..).flatten()` on `Iterator` --> $DIR/map_flatten_fixable.rs:18:47 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id)` | = note: `-D clippy::map-flatten` implied by `-D warnings` -help: try replacing `map` with `filter_map`, and remove the `.flatten()` - | -LL | let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(option_id).collect(); - | ~~~~~~~~~~~~~~~~~~~~~ error: called `map(..).flatten()` on `Iterator` --> $DIR/map_flatten_fixable.rs:19:47 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try replacing `map` with `filter_map`, and remove the `.flatten()` - | -LL | let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(option_id_ref).collect(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_ref)` error: called `map(..).flatten()` on `Iterator` --> $DIR/map_flatten_fixable.rs:20:47 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try replacing `map` with `filter_map`, and remove the `.flatten()` - | -LL | let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(option_id_closure).collect(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_closure)` error: called `map(..).flatten()` on `Iterator` --> $DIR/map_flatten_fixable.rs:21:47 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try replacing `map` with `filter_map`, and remove the `.flatten()` - | -LL | let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(|x| x.checked_add(1)).collect(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(|x| x.checked_add(1))` error: called `map(..).flatten()` on `Iterator` --> $DIR/map_flatten_fixable.rs:24:47 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try replacing `map` with `flat_map`, and remove the `.flatten()` - | -LL | let _: Vec<_> = vec![5_i8; 6].into_iter().flat_map(|x| 0..x).collect(); - | ~~~~~~~~~~~~~~~~~~ + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|x| 0..x)` error: called `map(..).flatten()` on `Option` --> $DIR/map_flatten_fixable.rs:27:40 | LL | let _: Option<_> = (Some(Some(1))).map(|x| x).flatten(); - | ^^^^^^^^^^^^^^^^^^^^ - | -help: try replacing `map` with `and_then`, and remove the `.flatten()` - | -LL | let _: Option<_> = (Some(Some(1))).and_then(|x| x); - | ~~~~~~~~~~~~~~~ + | ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)` error: called `map(..).flatten()` on `Result` --> $DIR/map_flatten_fixable.rs:30:42 | LL | let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten(); - | ^^^^^^^^^^^^^^^^^^^^ - | -help: try replacing `map` with `and_then`, and remove the `.flatten()` - | -LL | let _: Result<_, &str> = (Ok(Ok(1))).and_then(|x| x); - | ~~~~~~~~~~~~~~~ + | ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)` error: called `map(..).flatten()` on `Option` --> $DIR/map_flatten_fixable.rs:59:10 @@ -89,14 +55,12 @@ LL | | }) LL | | .flatten(); | |__________________^ | -help: try replacing `map` with `and_then` +help: try replacing `map` with `and_then` and remove the `.flatten()` | LL ~ .and_then(|_| { LL + // we need some newlines LL + // so that the span is big enough - | -help: and remove the `.flatten()` - | +LL + // for a splitted output of the diagnostic LL + Some("") LL + // whitespace beforehand is important as well LL ~ }); diff --git a/src/tools/clippy/tests/ui/or_fun_call.fixed b/src/tools/clippy/tests/ui/or_fun_call.fixed index 3208048e0d5..123aed40251 100644 --- a/src/tools/clippy/tests/ui/or_fun_call.fixed +++ b/src/tools/clippy/tests/ui/or_fun_call.fixed @@ -185,8 +185,7 @@ mod issue8239 { .reduce(|mut acc, f| { acc.push_str(&f); acc - }) - .unwrap_or_default(); + }).unwrap_or_default(); } fn more_to_max_suggestion_highest_lines_1() { @@ -198,8 +197,7 @@ mod issue8239 { let _ = ""; acc.push_str(&f); acc - }) - .unwrap_or_default(); + }).unwrap_or_default(); } fn equal_to_max_suggestion_highest_lines() { diff --git a/src/tools/clippy/tests/ui/or_fun_call.stderr b/src/tools/clippy/tests/ui/or_fun_call.stderr index 549b00ae3c4..dfe15654bc3 100644 --- a/src/tools/clippy/tests/ui/or_fun_call.stderr +++ b/src/tools/clippy/tests/ui/or_fun_call.stderr @@ -109,16 +109,50 @@ LL | None.unwrap_or( unsafe { ptr_to_ref(s) } ); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:189:14 + --> $DIR/or_fun_call.rs:182:9 + | +LL | / frames +LL | | .iter() +LL | | .map(|f: &String| f.to_lowercase()) +LL | | .reduce(|mut acc, f| { +... | +LL | | }) +LL | | .unwrap_or(String::new()); + | |_____________________________________^ + | +help: try this + | +LL ~ frames +LL + .iter() +LL + .map(|f: &String| f.to_lowercase()) +LL + .reduce(|mut acc, f| { +LL + acc.push_str(&f); +LL + acc +LL ~ }).unwrap_or_default(); | -LL | .unwrap_or(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:202:14 + --> $DIR/or_fun_call.rs:195:9 + | +LL | / iter.map(|f: &String| f.to_lowercase()) +LL | | .reduce(|mut acc, f| { +LL | | let _ = ""; +LL | | let _ = ""; +... | +LL | | }) +LL | | .unwrap_or(String::new()); + | |_____________________________________^ + | +help: try this + | +LL ~ iter.map(|f: &String| f.to_lowercase()) +LL + .reduce(|mut acc, f| { +LL + let _ = ""; +LL + let _ = ""; +LL + acc.push_str(&f); +LL + acc +LL ~ }).unwrap_or_default(); | -LL | .unwrap_or(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` --> $DIR/or_fun_call.rs:208:9 diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 5352f7c6fe0..31e979a574b 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -395,7 +395,29 @@ impl TestProps { ); config.set_name_directive(ln, STDERR_PER_BITWIDTH, &mut self.stderr_per_bitwidth); config.set_name_directive(ln, INCREMENTAL, &mut self.incremental); - config.set_name_directive(ln, KNOWN_BUG, &mut self.known_bug); + + // Unlike the other `name_value_directive`s this needs to be handled manually, + // because it sets a `bool` flag. + if let Some(known_bug) = config.parse_name_value_directive(ln, KNOWN_BUG) { + let known_bug = known_bug.trim(); + if known_bug == "unknown" + || known_bug.split(',').all(|issue_ref| { + issue_ref + .trim() + .split_once('#') + .filter(|(_, number)| { + number.chars().all(|digit| digit.is_numeric()) + }) + .is_some() + }) + { + self.known_bug = true; + } else { + panic!( + "Invalid known-bug value: {known_bug}\nIt requires comma-separated issue references (`#000` or `chalk#000`) or `unknown`." + ); + } + } config.set_name_value_directive(ln, MIR_UNIT_TEST, &mut self.mir_unit_test, |s| { s.trim().to_string() }); diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 04a1d257bc0..fe5195738c1 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -30,7 +30,7 @@ except ImportError: # These should be collaborators of the rust-lang/rust repository (with at least # read privileges on it). CI will fail otherwise. MAINTAINERS = { - 'miri': {'oli-obk', 'RalfJung', 'eddyb'}, + 'miri': {'oli-obk', 'RalfJung'}, 'rls': {'Xanewok'}, 'rustfmt': {'topecongiro', 'calebcartwright'}, 'book': {'carols10cents', 'steveklabnik'}, diff --git a/triagebot.toml b/triagebot.toml index cef78cc3b33..8aefb1f620b 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -215,3 +215,108 @@ changelog-path = "RELEASES.md" changelog-branch = "master" [shortcut] + + +[mentions."compiler/rustc_apfloat"] +message = """ +Changes rustc_apfloat. rustc_apfloat is currently in limbo and you almost +certainly don't want to change it (see #55993). +""" +cc = ["@eddyb"] + +[mentions."compiler/rustc_codegen_cranelift"] +cc = ["@bjorn3"] + +[mentions."compiler/rustc_codegen_gcc"] +cc = ["@antoyo"] + +[mentions."compiler/rustc_const_eval/src/interpret"] +message = "Some changes occurred to the CTFE / Miri engine" +cc = ["@rust-lang/miri"] + +[mentions."compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs"] +message = "Some changes occurred in need_type_info.rs" +cc = ["@lcnr"] + +[mentions."compiler/rustc_middle/src/mir/interpret"] +message = "Some changes occurred to the CTFE / Miri engine" +cc = ["@rust-lang/miri"] + +[mentions."compiler/rustc_mir_transform/src/"] +message = "Some changes occurred to MIR optimizations" +cc = ["@rust-lang/mir-opt"] + +[mentions."compiler/rustc_trait_selection/src/traits/const_evaluatable.rs"] +message = "Some changes occurred in const_evaluatable.rs" +cc = ["@lcnr"] + +[mentions."compiler/rustc_error_codes/src/error_codes.rs"] +message = "Some changes occurred in diagnostic error codes" +cc = ["@GuillaumeGomez"] + +[mentions."library"] +message = """ +Hey! It looks like you've submitted a new PR for the library teams! + +If this PR contains changes to any `rust-lang/rust` public library APIs then +please comment with `@rustbot label +T-libs-api -T-libs` to tag it +appropriately. If this PR contains changes to any unstable APIs please edit +the PR description to add a link to the relevant [API Change +Proposal](https://std-dev-guide.rust-lang.org/feature-lifecycle/api-change-proposals.html) +or [create one](https://github.com/rust-lang/libs-team/issues/new?assignees=&labels=api-change-proposal%2C+T-libs-api&template=api-change-proposal.md&title=%28My+API+Change+Proposal%29) +if you haven't already. If you're unsure where your change falls no worries, +just leave it as is and the reviewer will take a look and make a decision to +forward on if necessary. + +Examples of `T-libs-api` changes: + +* Stabilizing library features +* Introducing insta-stable changes such as new implementations of existing + stable traits on existing stable types +* Introducing new or changing existing unstable library APIs (excluding + permanently unstable features / features without a tracking issue) +* Changing public documentation in ways that create new stability guarantees +* Changing observable runtime behavior of library APIs +""" + +[mentions."src/librustdoc/clean/types.rs"] +cc = ["@camelid"] + +[mentions."src/librustdoc/html/static"] +message = "Some changes occurred in HTML/CSS/JS." +cc = [ + "@GuillaumeGomez", + "@Folyd", + "@jsha", +] + +[mentions."src/librustdoc/html/static/css/themes"] +message = "Some changes occurred in HTML/CSS themes." +cc = ["@GuillaumeGomez"] + +[mentions."src/librustdoc/html/static/css/themes/ayu.css"] +message = "A change occurred in the Ayu theme." +cc = ["@Cldfire"] + +[mentions."src/rustdoc-json-types"] +message = """ +rustdoc-json-types is a **public** (although nightly-only) API. +If possible, consider changing `src/librustdoc/json/conversions.rs`; +otherwise, make sure you bump the `FORMAT_VERSION` constant. +""" +cc = [ + "@CraftSpider", + "@aDotInTheVoid", +] + +[mentions."src/tools/cargo"] +cc = ["@ehuss"] + +[mentions."src/tools/clippy"] +cc = ["@rust-lang/clippy"] + +[mentions."src/tools/miri"] +cc = ["@rust-lang/miri"] + +[mentions."src/tools/rustfmt"] +cc = ["@rust-lang/rustfmt"] |
